Merge tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Mar 2012 01:57:40 +0000 (18:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 30 Mar 2012 01:57:40 +0000 (18:57 -0700)
Pull devicetree documentation update from Grant Likely.

* tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux-2.6:
  dt: Linux DT usage model documentation
  mtd: Move fdt partition documentation to a seperate file

2710 files changed:
Documentation/ABI/testing/debugfs-olpc [new file with mode: 0644]
Documentation/ABI/testing/sysfs-block-dm [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-samsung-laptop
Documentation/Makefile
Documentation/device-mapper/thin-provisioning.txt
Documentation/device-mapper/verity.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-omap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-twl4030.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/sodaville.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt [new file with mode: 0644]
Documentation/dma-buf-sharing.txt
Documentation/filesystems/files.txt
Documentation/gpio.txt
Documentation/i2c/busses/i2c-i801
Documentation/kernel-parameters.txt
Documentation/laptops/asus-laptop.txt
Documentation/laptops/sony-laptop.txt
Documentation/virtual/kvm/api.txt
Documentation/virtual/kvm/ppc-pv.txt
Documentation/vm/Makefile [deleted file]
Documentation/vm/hugepage-mmap.c [deleted file]
Documentation/vm/hugepage-shm.c [deleted file]
Documentation/vm/map_hugetlb.c [deleted file]
Documentation/vm/page-types.c [deleted file]
Documentation/watchdog/00-INDEX [deleted file]
Documentation/watchdog/convert_drivers_to_kernel_api.txt
Documentation/watchdog/watchdog-kernel-api.txt
MAINTAINERS
arch/Kconfig
arch/alpha/boot/bootp.c
arch/alpha/boot/bootpz.c
arch/alpha/boot/head.S
arch/alpha/boot/main.c
arch/alpha/include/asm/atomic.h
arch/alpha/include/asm/auxvec.h
arch/alpha/include/asm/core_lca.h
arch/alpha/include/asm/core_mcpcia.h
arch/alpha/include/asm/core_t2.h
arch/alpha/include/asm/elf.h
arch/alpha/include/asm/exec.h [new file with mode: 0644]
arch/alpha/include/asm/fpu.h
arch/alpha/include/asm/io.h
arch/alpha/include/asm/irqflags.h
arch/alpha/include/asm/mce.h [new file with mode: 0644]
arch/alpha/include/asm/mmu_context.h
arch/alpha/include/asm/pal.h
arch/alpha/include/asm/pgtable.h
arch/alpha/include/asm/posix_types.h
arch/alpha/include/asm/setup.h
arch/alpha/include/asm/special_insns.h [new file with mode: 0644]
arch/alpha/include/asm/spinlock.h
arch/alpha/include/asm/switch_to.h [new file with mode: 0644]
arch/alpha/include/asm/system.h [deleted file]
arch/alpha/include/asm/xchg.h
arch/alpha/kernel/core_apecs.c
arch/alpha/kernel/core_cia.c
arch/alpha/kernel/core_t2.c
arch/alpha/kernel/err_impl.h
arch/alpha/kernel/head.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_eiger.c
arch/alpha/kernel/sys_jensen.c
arch/alpha/kernel/sys_marvel.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_ruffian.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_sio.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/sys_titan.c
arch/alpha/kernel/sys_wildfire.c
arch/alpha/kernel/traps.c
arch/alpha/kernel/vmlinux.lds.S
arch/alpha/lib/stacktrace.c
arch/alpha/mm/fault.c
arch/alpha/mm/init.c
arch/alpha/oprofile/common.c
arch/alpha/oprofile/op_model_ev4.c
arch/alpha/oprofile/op_model_ev5.c
arch/alpha/oprofile/op_model_ev6.c
arch/alpha/oprofile/op_model_ev67.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/decompress.c
arch/arm/boot/compressed/piggy.xzkern.S [new file with mode: 0644]
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/common/gic.c
arch/arm/common/pl330.c [deleted file]
arch/arm/common/via82c505.c
arch/arm/configs/integrator_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/atomic.h
arch/arm/include/asm/barrier.h [new file with mode: 0644]
arch/arm/include/asm/bitops.h
arch/arm/include/asm/bug.h
arch/arm/include/asm/cmpxchg.h [new file with mode: 0644]
arch/arm/include/asm/compiler.h [new file with mode: 0644]
arch/arm/include/asm/cp15.h [new file with mode: 0644]
arch/arm/include/asm/div64.h
arch/arm/include/asm/dma.h
arch/arm/include/asm/domain.h
arch/arm/include/asm/elf.h
arch/arm/include/asm/exec.h [new file with mode: 0644]
arch/arm/include/asm/hardware/cache-l2x0.h
arch/arm/include/asm/hardware/iop3xx.h
arch/arm/include/asm/hardware/iop_adma.h
arch/arm/include/asm/hardware/it8152.h
arch/arm/include/asm/hardware/pl330.h [deleted file]
arch/arm/include/asm/io.h
arch/arm/include/asm/irq.h
arch/arm/include/asm/jump_label.h [new file with mode: 0644]
arch/arm/include/asm/mc146818rtc.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/mmu.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/opcodes.h
arch/arm/include/asm/page.h
arch/arm/include/asm/perf_event.h
arch/arm/include/asm/posix_types.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/prom.h
arch/arm/include/asm/switch_to.h [new file with mode: 0644]
arch/arm/include/asm/system.h
arch/arm/include/asm/system_info.h [new file with mode: 0644]
arch/arm/include/asm/system_misc.h [new file with mode: 0644]
arch/arm/include/asm/tlbflush.h
arch/arm/include/asm/traps.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/Makefile
arch/arm/kernel/armksyms.c
arch/arm/kernel/debug.S
arch/arm/kernel/elf.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c
arch/arm/kernel/ftrace.c
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/insn.c [new file with mode: 0644]
arch/arm/kernel/insn.h [new file with mode: 0644]
arch/arm/kernel/irq.c
arch/arm/kernel/jump_label.c [new file with mode: 0644]
arch/arm/kernel/kprobes-common.c
arch/arm/kernel/kprobes.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/patch.c [new file with mode: 0644]
arch/arm/kernel/patch.h [new file with mode: 0644]
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/sched_clock.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/sleep.S
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c
arch/arm/kernel/tcm.c
arch/arm/kernel/thumbee.c
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/include/mach/at_hdmac.h
arch/arm/mach-at91/include/mach/io.h [deleted file]
arch/arm/mach-at91/include/mach/system_rev.h
arch/arm/mach-at91/include/mach/uncompress.h
arch/arm/mach-bcmring/include/mach/io.h [deleted file]
arch/arm/mach-clps711x/common.c
arch/arm/mach-clps711x/include/mach/io.h [deleted file]
arch/arm/mach-clps711x/include/mach/uncompress.h
arch/arm/mach-clps711x/p720t-leds.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-cns3xxx/devices.c
arch/arm/mach-cns3xxx/include/mach/io.h [deleted file]
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/include/mach/entry-macro.S
arch/arm/mach-davinci/include/mach/hardware.h
arch/arm/mach-davinci/include/mach/io.h [deleted file]
arch/arm/mach-davinci/include/mach/uncompress.h
arch/arm/mach-davinci/time.c
arch/arm/mach-dove/addr-map.c
arch/arm/mach-dove/include/mach/io.h
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ebsa110/include/mach/io.h
arch/arm/mach-ebsa110/leds.c
arch/arm/mach-ep93xx/include/mach/io.h [deleted file]
arch/arm/mach-exynos/hotplug.c
arch/arm/mach-exynos/include/mach/io.h [deleted file]
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/ebsa285-leds.c
arch/arm/mach-footbridge/include/mach/io.h
arch/arm/mach-footbridge/netwinder-hw.c
arch/arm/mach-footbridge/netwinder-leds.c
arch/arm/mach-gemini/include/mach/io.h [deleted file]
arch/arm/mach-h720x/include/mach/io.h [deleted file]
arch/arm/mach-highbank/highbank.c
arch/arm/mach-highbank/include/mach/io.h [deleted file]
arch/arm/mach-highbank/include/mach/irqs.h [deleted file]
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/dma-v1.c [deleted file]
arch/arm/mach-imx/include/mach/dma-v1.h [deleted file]
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-mx51_efikamx.c
arch/arm/mach-imx/mach-mx51_efikasb.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/include/mach/io.h
arch/arm/mach-integrator/include/mach/irqs.h
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-integrator/leds.c
arch/arm/mach-integrator/pci.c
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-iop13xx/include/mach/io.h
arch/arm/mach-iop13xx/include/mach/iop13xx.h
arch/arm/mach-iop13xx/io.c
arch/arm/mach-iop13xx/iq81340mc.c
arch/arm/mach-iop13xx/iq81340sc.c
arch/arm/mach-iop13xx/pci.h [new file with mode: 0644]
arch/arm/mach-iop32x/include/mach/io.h
arch/arm/mach-iop33x/include/mach/io.h
arch/arm/mach-iop33x/uart.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp2000/enp2611.c
arch/arm/mach-ixp2000/include/mach/io.h
arch/arm/mach-ixp2000/ixdp2400.c
arch/arm/mach-ixp2000/ixdp2800.c
arch/arm/mach-ixp2000/ixdp2x00.c
arch/arm/mach-ixp2000/ixdp2x01.c
arch/arm/mach-ixp2000/pci.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp23xx/espresso.c
arch/arm/mach-ixp23xx/include/mach/io.h
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/pci.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/avila-setup.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/coyote-setup.c
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/fsg-setup.c
arch/arm/mach-ixp4xx/gateway7001-setup.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/gtwx5715-setup.c
arch/arm/mach-ixp4xx/include/mach/hardware.h
arch/arm/mach-ixp4xx/include/mach/io.h
arch/arm/mach-ixp4xx/include/mach/platform.h
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-ixp4xx/omixp-setup.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm/mach-ixp4xx/wg302v2-setup.c
arch/arm/mach-kirkwood/include/mach/io.h
arch/arm/mach-ks8695/include/mach/io.h [deleted file]
arch/arm/mach-ks8695/time.c
arch/arm/mach-lpc32xx/include/mach/io.h [deleted file]
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/avengers_lite.c
arch/arm/mach-mmp/brownstone.c
arch/arm/mach-mmp/common.c
arch/arm/mach-mmp/flint.c
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-mmp/include/mach/addr-map.h
arch/arm/mach-mmp/include/mach/io.h [deleted file]
arch/arm/mach-mmp/include/mach/irqs.h
arch/arm/mach-mmp/irq-mmp2.c
arch/arm/mach-mmp/jasper.c
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-mmp/tavorevb.c
arch/arm/mach-mmp/teton_bga.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-msm/board-halibut.c
arch/arm/mach-msm/board-sapphire.c
arch/arm/mach-msm/board-trout.c
arch/arm/mach-msm/include/mach/io.h [deleted file]
arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
arch/arm/mach-msm/include/mach/msm_iomap-8960.h
arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
arch/arm/mach-msm/include/mach/msm_iomap.h
arch/arm/mach-msm/io.c
arch/arm/mach-msm/timer.c
arch/arm/mach-mv78xx0/include/mach/io.h
arch/arm/mach-mxs/include/mach/hardware.h
arch/arm/mach-mxs/include/mach/io.h [deleted file]
arch/arm/mach-mxs/system.c
arch/arm/mach-netx/generic.c
arch/arm/mach-netx/include/mach/hardware.h
arch/arm/mach-netx/include/mach/io.h [deleted file]
arch/arm/mach-netx/include/mach/netx-regs.h
arch/arm/mach-nomadik/include/mach/io.h [deleted file]
arch/arm/mach-omap1/ams-delta-fiq-handler.S
arch/arm/mach-omap1/id.c
arch/arm/mach-omap1/include/mach/entry-macro.S
arch/arm/mach-omap1/include/mach/io.h [deleted file]
arch/arm/mach-omap1/iomap.h
arch/arm/mach-omap1/leds-h2p2-debug.c
arch/arm/mach-omap1/leds-innovator.c
arch/arm/mach-omap1/leds-osk.c
arch/arm/mach-omap1/mux.c
arch/arm/mach-omap1/sleep.S
arch/arm/mach-omap1/sram.S
arch/arm/mach-omap1/time.c
arch/arm/mach-omap1/timer32k.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/hsmmc.h
arch/arm/mach-omap2/include/mach/io.h [deleted file]
arch/arm/mach-omap2/iomap.h
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm44xx.c
arch/arm/mach-omap2/sleep44xx.S
arch/arm/mach-orion5x/common.c
arch/arm/mach-orion5x/common.h
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/include/mach/io.h [deleted file]
arch/arm/mach-orion5x/ls-chl-setup.c
arch/arm/mach-orion5x/ls_hgl-setup.c
arch/arm/mach-orion5x/lsmini-setup.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-orion5x/tsx09-common.c
arch/arm/mach-picoxcell/include/mach/io.h [deleted file]
arch/arm/mach-picoxcell/include/mach/irqs.h [deleted file]
arch/arm/mach-pnx4008/core.c
arch/arm/mach-pnx4008/dma.c
arch/arm/mach-pnx4008/include/mach/io.h [deleted file]
arch/arm/mach-pnx4008/irq.c
arch/arm/mach-pnx4008/time.c
arch/arm/mach-prima2/include/mach/io.h [deleted file]
arch/arm/mach-prima2/timer.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/capc7117.c
arch/arm/mach-pxa/clock-pxa2xx.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/colibri-pxa3xx.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/corgi_pm.c
arch/arm/mach-pxa/cpufreq-pxa3xx.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/h5000.c
arch/arm/mach-pxa/himalaya.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/include/mach/hardware.h
arch/arm/mach-pxa/include/mach/io.h [deleted file]
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/include/mach/mainstone.h
arch/arm/mach-pxa/leds-idp.c
arch/arm/mach-pxa/leds-lubbock.c
arch/arm/mach-pxa/leds-mainstone.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mfp-pxa2xx.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/mp900.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa2xx.c
arch/arm/mach-pxa/pxa300.c
arch/arm/mach-pxa/pxa320.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/reset.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/sharpsl_pm.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/time.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/xcep.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-realview/core.c
arch/arm/mach-realview/hotplug.c
arch/arm/mach-realview/include/mach/hardware.h
arch/arm/mach-realview/include/mach/io.h [deleted file]
arch/arm/mach-rpc/include/mach/hardware.h
arch/arm/mach-rpc/include/mach/io.h
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-s3c24xx/include/mach/io.h
arch/arm/mach-s3c24xx/s3c2410.c
arch/arm/mach-s3c24xx/s3c2412.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s3c24xx/s3c244x.c
arch/arm/mach-s3c64xx/common.c
arch/arm/mach-s3c64xx/include/mach/io.h [deleted file]
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5p64x0/include/mach/io.h [deleted file]
arch/arm/mach-s5pc100/common.c
arch/arm/mach-s5pc100/include/mach/io.h [deleted file]
arch/arm/mach-s5pv210/include/mach/io.h [deleted file]
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/include/mach/io.h [deleted file]
arch/arm/mach-sa1100/leds-assabet.c
arch/arm/mach-sa1100/leds-badge4.c
arch/arm/mach-sa1100/leds-cerf.c
arch/arm/mach-sa1100/leds-hackkit.c
arch/arm/mach-sa1100/leds-lart.c
arch/arm/mach-sa1100/pm.c
arch/arm/mach-shark/include/mach/io.h
arch/arm/mach-shark/leds.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-bonito.c
arch/arm/mach-shmobile/board-g3evm.c
arch/arm/mach-shmobile/board-g4evm.c
arch/arm/mach-shmobile/board-kota2.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/cpuidle.c
arch/arm/mach-shmobile/include/mach/io.h [deleted file]
arch/arm/mach-shmobile/include/mach/irqs.h
arch/arm/mach-shmobile/include/mach/system.h
arch/arm/mach-shmobile/intc-r8a7740.c
arch/arm/mach-shmobile/intc-r8a7779.c
arch/arm/mach-shmobile/intc-sh7367.c
arch/arm/mach-shmobile/intc-sh7372.c
arch/arm/mach-shmobile/intc-sh7377.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/pm-r8a7779.c
arch/arm/mach-shmobile/pm-sh7372.c
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-sh7367.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/setup-sh7377.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-sh73a0.c
arch/arm/mach-shmobile/suspend.c
arch/arm/mach-spear3xx/clock.c
arch/arm/mach-spear3xx/include/mach/io.h [deleted file]
arch/arm/mach-spear6xx/clock.c
arch/arm/mach-spear6xx/include/mach/io.h [deleted file]
arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/hotplug.c
arch/arm/mach-tegra/include/mach/debug-macro.S
arch/arm/mach-tegra/include/mach/io.h
arch/arm/mach-tegra/include/mach/iomap.h
arch/arm/mach-tegra/io.c
arch/arm/mach-tegra/sleep.S
arch/arm/mach-u300/include/mach/io.h [deleted file]
arch/arm/mach-u300/include/mach/u300-regs.h
arch/arm/mach-ux500/include/mach/hardware.h
arch/arm/mach-ux500/include/mach/io.h [deleted file]
arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/include/mach/io.h [deleted file]
arch/arm/mach-versatile/pci.c
arch/arm/mach-vexpress/hotplug.c
arch/arm/mach-vexpress/include/mach/io.h [deleted file]
arch/arm/mach-vt8500/include/mach/io.h [deleted file]
arch/arm/mach-w90x900/cpu.c
arch/arm/mach-w90x900/include/mach/io.h [deleted file]
arch/arm/mach-zynq/include/mach/io.h [deleted file]
arch/arm/mm/alignment.c
arch/arm/mm/cache-feroceon-l2.c
arch/arm/mm/cache-l2x0.c
arch/arm/mm/cache-tauros2.c
arch/arm/mm/cache-xsc3l2.c
arch/arm/mm/copypage-v4mc.c
arch/arm/mm/copypage-v6.c
arch/arm/mm/copypage-xscale.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/highmem.c
arch/arm/mm/idmap.c
arch/arm/mm/init.c
arch/arm/mm/ioremap.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/pgd.c
arch/arm/mm/proc-fa526.S
arch/arm/mm/vmregion.c
arch/arm/mm/vmregion.h
arch/arm/net/Makefile [new file with mode: 0644]
arch/arm/net/bpf_jit_32.c [new file with mode: 0644]
arch/arm/net/bpf_jit_32.h [new file with mode: 0644]
arch/arm/nwfpe/fpa11.c
arch/arm/plat-iop/i2c.c
arch/arm/plat-iop/pci.c
arch/arm/plat-iop/restart.c
arch/arm/plat-mxc/include/mach/hardware.h
arch/arm/plat-mxc/include/mach/io.h [deleted file]
arch/arm/plat-mxc/system.c
arch/arm/plat-nomadik/Kconfig
arch/arm/plat-nomadik/include/plat/ste_dma40.h
arch/arm/plat-omap/debug-leds.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/plat/gpio.h
arch/arm/plat-omap/include/plat/hardware.h
arch/arm/plat-omap/include/plat/mmc.h
arch/arm/plat-omap/include/plat/sdrc.h
arch/arm/plat-omap/include/plat/usb.h
arch/arm/plat-pxa/dma.c
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-samsung/cpu.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/time.c
arch/arm/plat-spear/include/plat/hardware.h
arch/arm/plat-spear/include/plat/io.h [deleted file]
arch/arm/plat-spear/restart.c
arch/arm/plat-versatile/Kconfig
arch/arm/vfp/vfpmodule.c
arch/avr32/include/asm/atomic.h
arch/avr32/include/asm/barrier.h [new file with mode: 0644]
arch/avr32/include/asm/bitops.h
arch/avr32/include/asm/bug.h
arch/avr32/include/asm/cmpxchg.h [new file with mode: 0644]
arch/avr32/include/asm/exec.h [new file with mode: 0644]
arch/avr32/include/asm/posix_types.h
arch/avr32/include/asm/special_insns.h [new file with mode: 0644]
arch/avr32/include/asm/switch_to.h [new file with mode: 0644]
arch/avr32/include/asm/system.h [deleted file]
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/cpufreq.c
arch/avr32/mach-at32ap/include/mach/atmel-mci.h
arch/avr32/oprofile/op_model_avr32.c
arch/blackfin/include/asm/system.h [deleted file]
arch/c6x/Kconfig
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/barrier.h [new file with mode: 0644]
arch/c6x/include/asm/bitops.h
arch/c6x/include/asm/bug.h [new file with mode: 0644]
arch/c6x/include/asm/cmpxchg.h [new file with mode: 0644]
arch/c6x/include/asm/exec.h [new file with mode: 0644]
arch/c6x/include/asm/processor.h
arch/c6x/include/asm/setup.h
arch/c6x/include/asm/special_insns.h [new file with mode: 0644]
arch/c6x/include/asm/switch_to.h [new file with mode: 0644]
arch/c6x/include/asm/system.h [deleted file]
arch/c6x/kernel/irq.c
arch/c6x/kernel/setup.c
arch/c6x/kernel/soc.c
arch/c6x/kernel/time.c
arch/c6x/kernel/traps.c
arch/c6x/platforms/timer64.c
arch/cris/arch-v10/drivers/ds1302.c
arch/cris/arch-v10/drivers/gpio.c
arch/cris/arch-v10/drivers/i2c.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v10/drivers/sync_serial.c
arch/cris/arch-v10/kernel/debugport.c
arch/cris/arch-v10/kernel/dma.c
arch/cris/arch-v10/kernel/io_interface_mux.c
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v10/kernel/ptrace.c
arch/cris/arch-v10/kernel/setup.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v10/kernel/traps.c
arch/cris/arch-v32/drivers/i2c.c
arch/cris/arch-v32/drivers/mach-a3/gpio.c
arch/cris/arch-v32/drivers/mach-fs/gpio.c
arch/cris/arch-v32/kernel/debugport.c
arch/cris/arch-v32/kernel/fasttimer.c
arch/cris/arch-v32/kernel/ptrace.c
arch/cris/arch-v32/mach-a3/dma.c
arch/cris/arch-v32/mach-fs/dma.c
arch/cris/include/arch-v10/arch/elf.h
arch/cris/include/arch-v32/arch/elf.h
arch/cris/include/arch-v32/arch/system.h
arch/cris/include/asm/atomic.h
arch/cris/include/asm/barrier.h [new file with mode: 0644]
arch/cris/include/asm/bitops.h
arch/cris/include/asm/cmpxchg.h [new file with mode: 0644]
arch/cris/include/asm/exec.h [new file with mode: 0644]
arch/cris/include/asm/posix_types.h
arch/cris/include/asm/processor.h
arch/cris/include/asm/switch_to.h [new file with mode: 0644]
arch/cris/include/asm/system.h [deleted file]
arch/cris/kernel/irq.c
arch/cris/kernel/process.c
arch/cris/kernel/ptrace.c
arch/cris/kernel/setup.c
arch/cris/kernel/traps.c
arch/cris/mm/fault.c
arch/frv/include/asm/atomic.h
arch/frv/include/asm/barrier.h [new file with mode: 0644]
arch/frv/include/asm/bug.h
arch/frv/include/asm/cmpxchg.h [new file with mode: 0644]
arch/frv/include/asm/exec.h [new file with mode: 0644]
arch/frv/include/asm/posix_types.h
arch/frv/include/asm/switch_to.h [new file with mode: 0644]
arch/frv/include/asm/system.h [deleted file]
arch/frv/kernel/debug-stub.c
arch/frv/kernel/gdb-io.c
arch/frv/kernel/gdb-stub.c
arch/frv/kernel/irq-mb93091.c
arch/frv/kernel/irq-mb93093.c
arch/frv/kernel/irq-mb93493.c
arch/frv/kernel/irq.c
arch/frv/kernel/process.c
arch/frv/kernel/ptrace.c
arch/frv/kernel/traps.c
arch/frv/mm/fault.c
arch/frv/mm/init.c
arch/frv/mm/kmap.c
arch/h8300/include/asm/atomic.h
arch/h8300/include/asm/barrier.h [new file with mode: 0644]
arch/h8300/include/asm/bitops.h
arch/h8300/include/asm/bug.h
arch/h8300/include/asm/cmpxchg.h [new file with mode: 0644]
arch/h8300/include/asm/exec.h [new file with mode: 0644]
arch/h8300/include/asm/posix_types.h
arch/h8300/include/asm/processor.h
arch/h8300/include/asm/switch_to.h [new file with mode: 0644]
arch/h8300/include/asm/system.h [deleted file]
arch/h8300/kernel/irq.c
arch/h8300/kernel/process.c
arch/h8300/kernel/ptrace.c
arch/h8300/kernel/traps.c
arch/h8300/mm/fault.c
arch/h8300/mm/init.c
arch/h8300/mm/kmap.c
arch/h8300/mm/memory.c
arch/hexagon/include/asm/atomic.h
arch/hexagon/include/asm/barrier.h [new file with mode: 0644]
arch/hexagon/include/asm/bitops.h
arch/hexagon/include/asm/cmpxchg.h [new file with mode: 0644]
arch/hexagon/include/asm/exec.h [new file with mode: 0644]
arch/hexagon/include/asm/switch_to.h [new file with mode: 0644]
arch/hexagon/include/asm/system.h [deleted file]
arch/hexagon/kernel/ptrace.c
arch/hexagon/kernel/smp.c
arch/hexagon/kernel/vm_events.c
arch/ia64/dig/setup.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/sim/boot/bootloader.c
arch/ia64/hp/sim/boot/fw-emu.c
arch/ia64/hp/sim/simeth.c
arch/ia64/include/asm/acpi.h
arch/ia64/include/asm/atomic.h
arch/ia64/include/asm/auxvec.h
arch/ia64/include/asm/barrier.h [new file with mode: 0644]
arch/ia64/include/asm/cmpxchg.h [new file with mode: 0644]
arch/ia64/include/asm/exec.h [new file with mode: 0644]
arch/ia64/include/asm/futex.h
arch/ia64/include/asm/io.h
arch/ia64/include/asm/irqflags.h
arch/ia64/include/asm/kexec.h
arch/ia64/include/asm/kvm.h
arch/ia64/include/asm/kvm_host.h
arch/ia64/include/asm/mca_asm.h
arch/ia64/include/asm/page.h
arch/ia64/include/asm/pci.h
arch/ia64/include/asm/pgtable.h
arch/ia64/include/asm/posix_types.h
arch/ia64/include/asm/processor.h
arch/ia64/include/asm/sal.h
arch/ia64/include/asm/setup.h
arch/ia64/include/asm/sn/pda.h
arch/ia64/include/asm/spinlock.h
arch/ia64/include/asm/switch_to.h [new file with mode: 0644]
arch/ia64/include/asm/system.h [deleted file]
arch/ia64/include/asm/uv/uv.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/fsys.S
arch/ia64/kernel/fsyscall_gtod_data.h
arch/ia64/kernel/gate.S
arch/ia64/kernel/gate.lds.S
arch/ia64/kernel/head.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/ivt.S
arch/ia64/kernel/machvec.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/msi_ia64.c
arch/ia64/kernel/patch.c
arch/ia64/kernel/pci-dma.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/process.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/ia64/kernel/traps.c
arch/ia64/kernel/uncached.c
arch/ia64/kernel/unwind.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/kvm/kvm-ia64.c
arch/ia64/mm/fault.c
arch/ia64/mm/init.c
arch/ia64/oprofile/backtrace.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/sn2/prominfo_proc.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/sn2/timer.c
arch/ia64/sn/kernel/tiocx.c
arch/ia64/xen/xensetup.S
arch/m32r/include/asm/atomic.h
arch/m32r/include/asm/barrier.h [new file with mode: 0644]
arch/m32r/include/asm/bitops.h
arch/m32r/include/asm/cmpxchg.h [new file with mode: 0644]
arch/m32r/include/asm/dcache_clear.h [new file with mode: 0644]
arch/m32r/include/asm/exec.h [new file with mode: 0644]
arch/m32r/include/asm/local.h
arch/m32r/include/asm/posix_types.h
arch/m32r/include/asm/spinlock.h
arch/m32r/include/asm/switch_to.h [new file with mode: 0644]
arch/m32r/include/asm/system.h [deleted file]
arch/m32r/kernel/ptrace.c
arch/m32r/kernel/traps.c
arch/m32r/mm/fault-nommu.c
arch/m32r/mm/fault.c
arch/m32r/platforms/m32104ut/setup.c
arch/m32r/platforms/m32700ut/setup.c
arch/m32r/platforms/mappi/setup.c
arch/m32r/platforms/mappi2/setup.c
arch/m32r/platforms/mappi3/setup.c
arch/m32r/platforms/oaks32r/setup.c
arch/m32r/platforms/opsput/setup.c
arch/m32r/platforms/usrv/setup.c
arch/m68k/amiga/amisound.c
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/atari/ataints.c
arch/m68k/atari/atasound.c
arch/m68k/atari/config.c
arch/m68k/bvme6000/config.c
arch/m68k/bvme6000/rtc.c
arch/m68k/hp300/time.c
arch/m68k/include/asm/atomic.h
arch/m68k/include/asm/barrier.h [new file with mode: 0644]
arch/m68k/include/asm/cmpxchg.h [new file with mode: 0644]
arch/m68k/include/asm/exec.h [new file with mode: 0644]
arch/m68k/include/asm/posix_types.h
arch/m68k/include/asm/sun3xflop.h
arch/m68k/include/asm/switch_to.h [new file with mode: 0644]
arch/m68k/include/asm/system.h [deleted file]
arch/m68k/kernel/ints.c
arch/m68k/kernel/irq.c
arch/m68k/kernel/process.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/traps.c
arch/m68k/kernel/vectors.c
arch/m68k/mac/config.c
arch/m68k/mac/misc.c
arch/m68k/mm/fault.c
arch/m68k/mm/init_mm.c
arch/m68k/mm/init_no.c
arch/m68k/mm/kmap.c
arch/m68k/mm/memory.c
arch/m68k/mm/motorola.c
arch/m68k/mm/sun3mmu.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/mvme16x/rtc.c
arch/m68k/platform/68328/config.c
arch/m68k/platform/68328/timers.c
arch/m68k/platform/68360/config.c
arch/m68k/platform/68EZ328/config.c
arch/m68k/platform/68VZ328/config.c
arch/m68k/q40/config.c
arch/m68k/q40/q40ints.c
arch/m68k/sun3/intersil.c
arch/m68k/sun3/mmu_emu.c
arch/m68k/sun3/prom/console.c
arch/m68k/sun3x/config.c
arch/m68k/sun3x/time.c
arch/microblaze/include/asm/atomic.h
arch/microblaze/include/asm/barrier.h [new file with mode: 0644]
arch/microblaze/include/asm/cmpxchg.h [new file with mode: 0644]
arch/microblaze/include/asm/exec.h [new file with mode: 0644]
arch/microblaze/include/asm/page.h
arch/microblaze/include/asm/processor.h
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/switch_to.h [new file with mode: 0644]
arch/microblaze/include/asm/system.h [deleted file]
arch/microblaze/kernel/cpu/pvr.c
arch/microblaze/kernel/microblaze_ksyms.c
arch/microblaze/kernel/process.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/timer.c
arch/microblaze/kernel/traps.c
arch/microblaze/lib/memcpy.c
arch/microblaze/mm/fault.c
arch/mips/Kconfig
arch/mips/cavium-octeon/setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/configs/db1300_defconfig
arch/mips/dec/ecc-berr.c
arch/mips/dec/kn01-berr.c
arch/mips/dec/kn02xa-berr.c
arch/mips/dec/wbflush.c
arch/mips/emma/markeins/irq.c
arch/mips/fw/arc/misc.c
arch/mips/include/asm/atomic.h
arch/mips/include/asm/barrier.h
arch/mips/include/asm/cmpxchg.h
arch/mips/include/asm/dma.h
arch/mips/include/asm/exec.h [new file with mode: 0644]
arch/mips/include/asm/mach-au1x00/au1000_dma.h
arch/mips/include/asm/posix_types.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/setup.h
arch/mips/include/asm/switch_to.h [new file with mode: 0644]
arch/mips/include/asm/system.h [deleted file]
arch/mips/include/asm/txx9/jmr3927.h
arch/mips/kernel/cpu-bugs64.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/irq-rm7000.c
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/irq.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/kspd.c
arch/mips/kernel/mips-mt.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc-proc.c
arch/mips/kernel/smtc.c
arch/mips/kernel/spram.c
arch/mips/kernel/syscall.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vpe.c
arch/mips/lasat/reset.c
arch/mips/math-emu/dsemul.c
arch/mips/mipssim/sim_smtc.c
arch/mips/mipssim/sim_time.c
arch/mips/mm/c-octeon.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-tx39.c
arch/mips/mm/fault.c
arch/mips/mm/page.c
arch/mips/mm/sc-ip22.c
arch/mips/mm/sc-mips.c
arch/mips/mm/sc-r5k.c
arch/mips/mm/tlb-r3k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlb-r8k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-time.c
arch/mips/netlogic/common/irq.c
arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
arch/mips/pmc-sierra/msp71xx/msp_irq_per.c
arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
arch/mips/pmc-sierra/yosemite/irq.c
arch/mips/pmc-sierra/yosemite/prom.c
arch/mips/pnx833x/common/interrupts.c
arch/mips/powertv/asic/asic_int.c
arch/mips/powertv/asic/irq_asic.c
arch/mips/powertv/init.c
arch/mips/rb532/irq.c
arch/mips/sgi-ip22/ip22-berr.c
arch/mips/sgi-ip22/ip22-reset.c
arch/mips/sgi-ip22/ip28-berr.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-reset.c
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sgi-ip32/ip32-reset.c
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/common/sb_tbprof.c
arch/mips/sibyte/sb1250/bus_watcher.c
arch/mips/sibyte/sb1250/irq.c
arch/mips/sni/reset.c
arch/mips/vr41xx/common/irq.c
arch/mips/vr41xx/common/pmu.c
arch/mn10300/include/asm/atomic.h
arch/mn10300/include/asm/barrier.h [new file with mode: 0644]
arch/mn10300/include/asm/cmpxchg.h [new file with mode: 0644]
arch/mn10300/include/asm/dma.h
arch/mn10300/include/asm/exec.h [new file with mode: 0644]
arch/mn10300/include/asm/posix_types.h
arch/mn10300/include/asm/switch_to.h [new file with mode: 0644]
arch/mn10300/include/asm/system.h [deleted file]
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/fpu.c
arch/mn10300/kernel/gdb-io-serial.c
arch/mn10300/kernel/gdb-io-ttysm.c
arch/mn10300/kernel/gdb-stub.c
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/mn10300-watchdog.c
arch/mn10300/kernel/process.c
arch/mn10300/kernel/ptrace.c
arch/mn10300/kernel/setup.c
arch/mn10300/kernel/smp-low.S
arch/mn10300/kernel/smp.c
arch/mn10300/kernel/traps.c
arch/mn10300/lib/bitops.c
arch/mn10300/mm/fault.c
arch/mn10300/mm/init.c
arch/mn10300/mm/misalignment.c
arch/mn10300/mm/pgtable.c
arch/mn10300/mm/tlb-smp.c
arch/mn10300/proc-mn2ws0050/proc-init.c
arch/openrisc/include/asm/Kbuild
arch/openrisc/include/asm/system.h [deleted file]
arch/openrisc/kernel/idle.c
arch/openrisc/kernel/process.c
arch/openrisc/kernel/prom.c
arch/openrisc/kernel/ptrace.c
arch/openrisc/kernel/setup.c
arch/openrisc/kernel/traps.c
arch/openrisc/mm/init.c
arch/openrisc/mm/tlb.c
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/barrier.h [new file with mode: 0644]
arch/parisc/include/asm/delay.h
arch/parisc/include/asm/dma.h
arch/parisc/include/asm/exec.h [new file with mode: 0644]
arch/parisc/include/asm/ldcw.h [new file with mode: 0644]
arch/parisc/include/asm/posix_types.h
arch/parisc/include/asm/processor.h
arch/parisc/include/asm/psw.h
arch/parisc/include/asm/special_insns.h [new file with mode: 0644]
arch/parisc/include/asm/spinlock.h
arch/parisc/include/asm/switch_to.h [new file with mode: 0644]
arch/parisc/include/asm/system.h [deleted file]
arch/parisc/include/asm/thread_info.h
arch/parisc/include/asm/timex.h
arch/parisc/include/asm/uaccess.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/firmware.c
arch/parisc/kernel/pci.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/traps.c
arch/parisc/lib/bitops.c
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/boot/.gitignore
arch/powerpc/configs/85xx/p1023rds_defconfig
arch/powerpc/configs/chroma_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/auxvec.h
arch/powerpc/include/asm/barrier.h [new file with mode: 0644]
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/cmpxchg.h [new file with mode: 0644]
arch/powerpc/include/asm/debug.h [new file with mode: 0644]
arch/powerpc/include/asm/dma.h
arch/powerpc/include/asm/exec.h [new file with mode: 0644]
arch/powerpc/include/asm/hw_breakpoint.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/kvm.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_32.h
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/include/asm/kvm_e500.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_para.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/posix_types.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/runlatch.h [new file with mode: 0644]
arch/powerpc/include/asm/setup.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/switch_to.h [new file with mode: 0644]
arch/powerpc/include/asm/system.h [deleted file]
arch/powerpc/include/asm/udbg.h
arch/powerpc/include/asm/vio.h
arch/powerpc/kernel/align.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/kvm_emul.S
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/ptrace32.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/softemu8xx.c
arch/powerpc/kernel/swsusp.c
arch/powerpc/kernel/swsusp_64.c
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_emulate.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_paired_singles.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/booke.h
arch/powerpc/kvm/booke_emulate.c
arch/powerpc/kvm/booke_interrupts.S
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500_emulate.c
arch/powerpc/kvm/e500_tlb.c
arch/powerpc/kvm/e500_tlb.h
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/kvm/trace.h
arch/powerpc/lib/alloc.c
arch/powerpc/lib/copyuser_power7_vmx.c
arch/powerpc/mm/44x_mmu.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/oprofile/common.c
arch/powerpc/oprofile/op_model_7450.c
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/oprofile/op_model_fsl_emb.c
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/oprofile/op_model_rs64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power4-pmu.c
arch/powerpc/perf/ppc970-pmu.c
arch/powerpc/platforms/52xx/lite5200_pm.c
arch/powerpc/platforms/82xx/pq2.c
arch/powerpc/platforms/83xx/km83xx.c
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc834x_itx.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/83xx/mpc836x_mds.c
arch/powerpc/platforms/83xx/sbc834x.c
arch/powerpc/platforms/83xx/suspend.c
arch/powerpc/platforms/85xx/corenet_ds.c
arch/powerpc/platforms/85xx/ge_imp3a.c
arch/powerpc/platforms/85xx/ksi8560.c
arch/powerpc/platforms/85xx/mpc8536_ds.c
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_rdb.c
arch/powerpc/platforms/85xx/p1010rdb.c
arch/powerpc/platforms/85xx/p1023_rds.c
arch/powerpc/platforms/85xx/p2041_rdb.c
arch/powerpc/platforms/85xx/p3041_ds.c
arch/powerpc/platforms/85xx/p4080_ds.c
arch/powerpc/platforms/85xx/p5020_ds.c
arch/powerpc/platforms/85xx/sbc8548.c
arch/powerpc/platforms/85xx/sbc8560.c
arch/powerpc/platforms/85xx/socrates.c
arch/powerpc/platforms/85xx/stx_gp3.c
arch/powerpc/platforms/85xx/tqm85xx.c
arch/powerpc/platforms/85xx/xes_mpc85xx.c
arch/powerpc/platforms/86xx/gef_ppc9a.c
arch/powerpc/platforms/86xx/gef_sbc310.c
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/pic.c
arch/powerpc/platforms/86xx/sbc8641d.c
arch/powerpc/platforms/8xx/mpc86xads_setup.c
arch/powerpc/platforms/8xx/mpc885ads_setup.c
arch/powerpc/platforms/8xx/tqm8xx_setup.c
arch/powerpc/platforms/cell/beat_htab.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/cell/spufs/coredump.c
arch/powerpc/platforms/embedded6xx/c2k.c
arch/powerpc/platforms/embedded6xx/holly.c
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
arch/powerpc/platforms/embedded6xx/prpmc2800.c
arch/powerpc/platforms/embedded6xx/storcenter.c
arch/powerpc/platforms/fsl_uli1575.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/maple/time.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/bootx_init.c
arch/powerpc/platforms/powermac/cpufreq_32.c
arch/powerpc/platforms/powermac/nvram.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/time.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/ps3/mm.c
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_dev.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/io_event_irq.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/powerpc/platforms/pseries/ras.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/wsp/chroma.c
arch/powerpc/platforms/wsp/psr2.c
arch/powerpc/platforms/wsp/wsp_pci.c
arch/powerpc/sysdev/cpm_common.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/msi_bitmap.c
arch/powerpc/sysdev/tsi108_dev.c
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/s390/crypto/crypt_s390.h
arch/s390/include/asm/atomic.h
arch/s390/include/asm/barrier.h [new file with mode: 0644]
arch/s390/include/asm/ctl_reg.h [new file with mode: 0644]
arch/s390/include/asm/elf.h
arch/s390/include/asm/exec.h [new file with mode: 0644]
arch/s390/include/asm/facility.h [new file with mode: 0644]
arch/s390/include/asm/kvm.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/mmu.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/posix_types.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/smp.h
arch/s390/include/asm/switch_to.h [new file with mode: 0644]
arch/s390/include/asm/system.h [deleted file]
arch/s390/include/asm/uaccess.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/cpcmd.c
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/lgr.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/os_info.c
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/suspend.c
arch/s390/kernel/traps.c
arch/s390/kernel/vdso.c
arch/s390/kvm/Kconfig
arch/s390/kvm/diag.c
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/maccess.c
arch/s390/mm/pgtable.c
arch/s390/oprofile/hwsampler.c
arch/score/include/asm/atomic.h
arch/score/include/asm/barrier.h [new file with mode: 0644]
arch/score/include/asm/bitops.h
arch/score/include/asm/bug.h
arch/score/include/asm/cmpxchg.h [new file with mode: 0644]
arch/score/include/asm/exec.h [new file with mode: 0644]
arch/score/include/asm/switch_to.h [new file with mode: 0644]
arch/score/include/asm/system.h [deleted file]
arch/sh/Kconfig
arch/sh/boards/mach-microdev/irq.c
arch/sh/include/asm/atomic-irq.h
arch/sh/include/asm/atomic.h
arch/sh/include/asm/auxvec.h
arch/sh/include/asm/barrier.h [new file with mode: 0644]
arch/sh/include/asm/bitops.h
arch/sh/include/asm/bl_bit.h [new file with mode: 0644]
arch/sh/include/asm/bl_bit_32.h [new file with mode: 0644]
arch/sh/include/asm/bl_bit_64.h [new file with mode: 0644]
arch/sh/include/asm/bug.h
arch/sh/include/asm/cache_insns.h [new file with mode: 0644]
arch/sh/include/asm/cache_insns_32.h [new file with mode: 0644]
arch/sh/include/asm/cache_insns_64.h [new file with mode: 0644]
arch/sh/include/asm/cmpxchg-irq.h
arch/sh/include/asm/cmpxchg.h [new file with mode: 0644]
arch/sh/include/asm/exec.h [new file with mode: 0644]
arch/sh/include/asm/futex-irq.h
arch/sh/include/asm/io.h
arch/sh/include/asm/irq.h
arch/sh/include/asm/posix_types_32.h
arch/sh/include/asm/posix_types_64.h
arch/sh/include/asm/processor.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/setup.h
arch/sh/include/asm/switch_to.h [new file with mode: 0644]
arch/sh/include/asm/switch_to_32.h [new file with mode: 0644]
arch/sh/include/asm/switch_to_64.h [new file with mode: 0644]
arch/sh/include/asm/system.h [deleted file]
arch/sh/include/asm/system_32.h [deleted file]
arch/sh/include/asm/system_64.h [deleted file]
arch/sh/include/asm/traps.h [new file with mode: 0644]
arch/sh/include/asm/traps_32.h [new file with mode: 0644]
arch/sh/include/asm/traps_64.h [new file with mode: 0644]
arch/sh/include/asm/uaccess.h
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/imask.c
arch/sh/kernel/cpu/sh2a/opcode_helper.c
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/hw_breakpoint.c
arch/sh/kernel/idle.c
arch/sh/kernel/io_trapped.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/reboot.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/smp.c
arch/sh/kernel/traps.c
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c
arch/sh/math-emu/math.c
arch/sh/mm/fault_32.c
arch/sh/mm/fault_64.c
arch/sh/mm/flush-sh4.c
arch/sh/mm/pmb.c
arch/sh/mm/tlb-pteaex.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlb-sh4.c
arch/sh/mm/tlbflush_64.c
arch/sparc/Kconfig
arch/sparc/include/asm/atomic_32.h
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/auxio_32.h
arch/sparc/include/asm/barrier.h [new file with mode: 0644]
arch/sparc/include/asm/barrier_32.h [new file with mode: 0644]
arch/sparc/include/asm/barrier_64.h [new file with mode: 0644]
arch/sparc/include/asm/bug.h
arch/sparc/include/asm/cacheflush_32.h
arch/sparc/include/asm/cacheflush_64.h
arch/sparc/include/asm/cmpxchg.h [new file with mode: 0644]
arch/sparc/include/asm/cmpxchg_32.h [new file with mode: 0644]
arch/sparc/include/asm/cmpxchg_64.h [new file with mode: 0644]
arch/sparc/include/asm/cpu_type.h [new file with mode: 0644]
arch/sparc/include/asm/exec.h [new file with mode: 0644]
arch/sparc/include/asm/floppy_32.h
arch/sparc/include/asm/futex_64.h
arch/sparc/include/asm/io_32.h
arch/sparc/include/asm/io_64.h
arch/sparc/include/asm/irqflags_32.h
arch/sparc/include/asm/mmu_context_64.h
arch/sparc/include/asm/ns87303.h
arch/sparc/include/asm/perfctr.h
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/posix_types.h
arch/sparc/include/asm/processor.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/setup.h
arch/sparc/include/asm/switch_to.h [new file with mode: 0644]
arch/sparc/include/asm/switch_to_32.h [new file with mode: 0644]
arch/sparc/include/asm/switch_to_64.h [new file with mode: 0644]
arch/sparc/include/asm/system.h [deleted file]
arch/sparc/include/asm/system_32.h [deleted file]
arch/sparc/include/asm/system_64.h [deleted file]
arch/sparc/include/asm/timer_32.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/include/asm/vio.h
arch/sparc/kernel/auxio_32.c
arch/sparc/kernel/devices.c
arch/sparc/kernel/ds.c
arch/sparc/kernel/irq.h
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/kgdb_32.c
arch/sparc/kernel/module.c
arch/sparc/kernel/muldiv.c
arch/sparc/kernel/nmi.c
arch/sparc/kernel/pcr.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/ptrace_32.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/reboot.c
arch/sparc/kernel/setup_32.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sigutil_32.c
arch/sparc/kernel/sigutil_64.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/time_32.c
arch/sparc/kernel/traps_32.c
arch/sparc/kernel/traps_64.c
arch/sparc/kernel/unaligned_32.c
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/vio.c
arch/sparc/kernel/visemul.c
arch/sparc/math-emu/math_64.c
arch/sparc/mm/btfixup.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/sparc/mm/init_64.h
arch/sparc/mm/loadmmu.c
arch/sparc/mm/tsb.c
arch/sparc/prom/console_32.c
arch/sparc/prom/console_64.c
arch/sparc/prom/misc_32.c
arch/sparc/prom/misc_64.c
arch/sparc/prom/p1275.c
arch/sparc/prom/ranges.c
arch/tile/include/asm/atomic.h
arch/tile/include/asm/atomic_32.h
arch/tile/include/asm/atomic_64.h
arch/tile/include/asm/barrier.h [new file with mode: 0644]
arch/tile/include/asm/bitops_32.h
arch/tile/include/asm/bitops_64.h
arch/tile/include/asm/cacheflush.h
arch/tile/include/asm/compat.h
arch/tile/include/asm/exec.h [new file with mode: 0644]
arch/tile/include/asm/pgtable.h
arch/tile/include/asm/setup.h
arch/tile/include/asm/smp.h
arch/tile/include/asm/spinlock_32.h
arch/tile/include/asm/switch_to.h [new file with mode: 0644]
arch/tile/include/asm/system.h [deleted file]
arch/tile/include/asm/timex.h
arch/tile/include/asm/unaligned.h
arch/tile/kernel/compat.c
arch/tile/kernel/early_printk.c
arch/tile/kernel/proc.c
arch/tile/kernel/process.c
arch/tile/kernel/regs_32.S
arch/tile/kernel/regs_64.S
arch/tile/kernel/single_step.c
arch/tile/kernel/smp.c
arch/tile/kernel/traps.c
arch/tile/mm/elf.c
arch/tile/mm/fault.c
arch/tile/mm/init.c
arch/tile/mm/pgtable.c
arch/um/include/asm/fixmap.h
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/barrier.h [new file with mode: 0644]
arch/unicore32/include/asm/bug.h [new file with mode: 0644]
arch/unicore32/include/asm/cmpxchg.h [new file with mode: 0644]
arch/unicore32/include/asm/exec.h [new file with mode: 0644]
arch/unicore32/include/asm/hwdef-copro.h [new file with mode: 0644]
arch/unicore32/include/asm/io.h
arch/unicore32/include/asm/switch_to.h [new file with mode: 0644]
arch/unicore32/include/asm/system.h [deleted file]
arch/unicore32/include/asm/uaccess.h
arch/unicore32/kernel/dma.c
arch/unicore32/kernel/head.S
arch/unicore32/kernel/hibernate.c
arch/unicore32/kernel/irq.c
arch/unicore32/kernel/ksyms.c
arch/unicore32/kernel/process.c
arch/unicore32/kernel/setup.h
arch/unicore32/kernel/traps.c
arch/unicore32/mm/alignment.c
arch/unicore32/mm/fault.c
arch/unicore32/mm/flush.c
arch/unicore32/mm/mm.h
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/ia32/ia32_aout.c
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/sys_ia32.c
arch/x86/include/asm/Kbuild
arch/x86/include/asm/apic.h
arch/x86/include/asm/auxvec.h
arch/x86/include/asm/barrier.h [new file with mode: 0644]
arch/x86/include/asm/bug.h
arch/x86/include/asm/cacheflush.h
arch/x86/include/asm/compat.h
arch/x86/include/asm/elf.h
arch/x86/include/asm/exec.h [new file with mode: 0644]
arch/x86/include/asm/futex.h
arch/x86/include/asm/i387.h
arch/x86/include/asm/ia32.h
arch/x86/include/asm/idle.h
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/kvm.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/local.h
arch/x86/include/asm/mc146818rtc.h
arch/x86/include/asm/mtrr.h
arch/x86/include/asm/page_types.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/posix_types.h
arch/x86/include/asm/posix_types_32.h
arch/x86/include/asm/posix_types_64.h
arch/x86/include/asm/posix_types_x32.h [new file with mode: 0644]
arch/x86/include/asm/processor.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/segment.h
arch/x86/include/asm/sigcontext.h
arch/x86/include/asm/sigframe.h
arch/x86/include/asm/sighandling.h [new file with mode: 0644]
arch/x86/include/asm/special_insns.h [new file with mode: 0644]
arch/x86/include/asm/stackprotector.h
arch/x86/include/asm/switch_to.h [new file with mode: 0644]
arch/x86/include/asm/sys_ia32.h
arch/x86/include/asm/syscall.h
arch/x86/include/asm/system.h [deleted file]
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/traps.h
arch/x86/include/asm/tsc.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/vgtod.h
arch/x86/include/asm/virtext.h
arch/x86/include/asm/x2apic.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/cstate.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mcheck/p5.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/mcheck/winchip.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/mtrr/if.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpuid.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/i8259.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/ldt.c
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/mca_32.c
arch/x86/kernel/module.c
arch/x86/kernel/msr.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kernel/syscall_64.c
arch/x86/kernel/tce_64.c
arch/x86/kernel/tls.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/vm86_32.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/i8259.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu_audit.c
arch/x86/kvm/pmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/math-emu/fpu_entry.c
arch/x86/mm/fault.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/pgtable_32.c
arch/x86/mm/srat.c
arch/x86/oprofile/backtrace.c
arch/x86/platform/ce4100/falconfalls.dts
arch/x86/platform/geode/Makefile
arch/x86/platform/geode/geos.c [new file with mode: 0644]
arch/x86/platform/olpc/olpc.c
arch/x86/power/cpu.c
arch/x86/power/hibernate_32.c
arch/x86/syscalls/Makefile
arch/x86/syscalls/syscall_32.tbl
arch/x86/syscalls/syscall_64.tbl
arch/x86/um/sys_call_table_64.c
arch/x86/um/user-offsets.c
arch/x86/vdso/.gitignore
arch/x86/vdso/Makefile
arch/x86/vdso/vclock_gettime.c
arch/x86/vdso/vdso32-setup.c
arch/x86/vdso/vdsox32.S [new file with mode: 0644]
arch/x86/vdso/vdsox32.lds.S [new file with mode: 0644]
arch/x86/vdso/vma.c
arch/xtensa/configs/iss_defconfig
arch/xtensa/include/asm/atomic.h
arch/xtensa/include/asm/barrier.h [new file with mode: 0644]
arch/xtensa/include/asm/bitops.h
arch/xtensa/include/asm/cmpxchg.h [new file with mode: 0644]
arch/xtensa/include/asm/exec.h [new file with mode: 0644]
arch/xtensa/include/asm/posix_types.h
arch/xtensa/include/asm/setup.h
arch/xtensa/include/asm/switch_to.h [new file with mode: 0644]
arch/xtensa/include/asm/system.h [deleted file]
arch/xtensa/include/asm/uaccess.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/ptrace.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/traps.c
arch/xtensa/mm/fault.c
arch/xtensa/mm/tlb.c
drivers/acpi/ec.c
drivers/acpi/processor_driver.c
drivers/acpi/video_detect.c
drivers/atm/eni.c
drivers/atm/firestream.c
drivers/atm/horizon.c
drivers/atm/idt77105.c
drivers/atm/iphase.c
drivers/atm/suni.c
drivers/atm/zatm.c
drivers/base/dma-buf.c
drivers/block/floppy.c
drivers/block/hd.c
drivers/block/nbd.c
drivers/block/sunvdc.c
drivers/block/xd.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/char/apm-emulation.c
drivers/char/ds1302.c
drivers/char/efirtc.c
drivers/char/genrtc.c
drivers/char/hpet.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_kcs_sm.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/lp.c
drivers/char/mbcs.c
drivers/char/mspec.c
drivers/char/mwave/3780i.c
drivers/char/nvram.c
drivers/char/nwflash.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/rtc.c
drivers/char/sonypi.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/clocksource/Kconfig
drivers/cpufreq/db8500-cpufreq.c
drivers/cpufreq/omap-cpufreq.c
drivers/cpufreq/powernow-k7.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/coh901318.c
drivers/dma/dmaengine.c
drivers/dma/dmaengine.h [new file with mode: 0644]
drivers/dma/dw_dmac.c
drivers/dma/dw_dmac_regs.h
drivers/dma/ep93xx_dma.c
drivers/dma/fsldma.c
drivers/dma/fsldma.h
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/intel_mid_dma_regs.h
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v3.c
drivers/dma/iop-adma.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/mpc512x_dma.c
drivers/dma/mv_xor.c
drivers/dma/mv_xor.h
drivers/dma/mxs-dma.c
drivers/dma/pch_dma.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/ppc4xx/adma.h
drivers/dma/shdma.c
drivers/dma/shdma.h
drivers/dma/sirf-dma.c
drivers/dma/ste_dma40.c
drivers/dma/timb_dma.c
drivers/dma/txx9dmac.c
drivers/dma/txx9dmac.h
drivers/edac/Kconfig
drivers/edac/edac_mc.c
drivers/edac/i5100_edac.c
drivers/edac/i5400_edac.c
drivers/edac/ppc4xx_edac.c
drivers/edac/sb_edac.c
drivers/firewire/core-cdev.c
drivers/firewire/core-device.c
drivers/firewire/core-topology.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-mc9s08dz60.c [new file with mode: 0644]
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-sodaville.c [new file with mode: 0644]
drivers/gpio/gpio-stmpe.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-tps65910.c
drivers/gpio/gpio-twl4030.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/gma500/mdfld_dsi_output.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/hwmon/fschmd.c
drivers/hwmon/mc13783-adc.c
drivers/hwmon/w83793.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-pcf.h
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-acorn.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-isch.c
drivers/i2c/i2c-boardinfo.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.h
drivers/i2c/i2c-dev.c
drivers/i2c/i2c-smbus.c
drivers/i2c/muxes/pca9541.c
drivers/i2c/muxes/pca954x.c
drivers/ide/ide-cs.c
drivers/ide/qd65xx.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/input/input-compat.c
drivers/input/input-compat.h
drivers/input/joydev.c
drivers/input/joystick/amijoy.c
drivers/input/misc/88pm860x_onkey.c
drivers/input/mouse/amimouse.c
drivers/input/mouse/atarimouse.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/maceps2.c
drivers/input/serio/rpckbd.c
drivers/input/serio/sa1111ps2.c
drivers/input/touchscreen/mc13783_ts.c
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/i4l/isdn_bsdcomp.c
drivers/isdn/pcbit/layer2.c
drivers/leds/leds-88pm860x.c
drivers/macintosh/macio-adb.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/therm_pm72.c
drivers/macintosh/therm_windtunnel.c
drivers/macintosh/via-cuda.c
drivers/macintosh/via-macii.c
drivers/macintosh/via-pmu.c
drivers/macintosh/via-pmu68k.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_pm121.c
drivers/macintosh/windfarm_pm81.c
drivers/macintosh/windfarm_pm91.c
drivers/macintosh/windfarm_smu_controls.c
drivers/macintosh/windfarm_smu_sensors.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-bufio.c
drivers/md/dm-bufio.h
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-exception-store.c
drivers/md/dm-flakey.c
drivers/md/dm-ioctl.c
drivers/md/dm-linear.c
drivers/md/dm-log.c
drivers/md/dm-mpath.c
drivers/md/dm-queue-length.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-round-robin.c
drivers/md/dm-service-time.c
drivers/md/dm-stripe.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/dm-verity.c [new file with mode: 0644]
drivers/md/dm.c
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-common.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/firewire/firedtv-fw.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/media-devnode.c
drivers/media/video/davinci/vpbe_osd.c
drivers/media/video/davinci/vpbe_venc.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/mx3_camera.c
drivers/media/video/timblogiw.c
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-dev.c
drivers/message/i2o/i2o_scsi.c
drivers/mfd/88pm860x-core.c
drivers/mfd/88pm860x-i2c.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-i2c.c
drivers/mfd/anatop-mfd.c [new file with mode: 0644]
drivers/mfd/asic3.c
drivers/mfd/da9052-core.c
drivers/mfd/da9052-i2c.c
drivers/mfd/da9052-spi.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/dbx500-prcmu-regs.h
drivers/mfd/mc13xxx-core.c
drivers/mfd/mcp-core.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/mfd-core.c
drivers/mfd/omap-usb-host.c
drivers/mfd/pcf50633-core.c
drivers/mfd/pcf50633-gpio.c
drivers/mfd/pcf50633-irq.c
drivers/mfd/rc5t583-irq.c [new file with mode: 0644]
drivers/mfd/rc5t583.c [new file with mode: 0644]
drivers/mfd/s5m-core.c
drivers/mfd/s5m-irq.c
drivers/mfd/sm501.c
drivers/mfd/stmpe.c
drivers/mfd/tps65090.c [new file with mode: 0644]
drivers/mfd/tps65217.c [new file with mode: 0644]
drivers/mfd/tps65910-irq.c
drivers/mfd/tps65910.c
drivers/mfd/twl-core.c
drivers/mfd/twl-core.h
drivers/mfd/twl4030-irq.c
drivers/mfd/twl6030-irq.c
drivers/mfd/wm831x-spi.c
drivers/mfd/wm8400-core.c
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-regmap.c
drivers/misc/sgi-gru/gru_instructions.h
drivers/misc/sgi-xp/xp.h
drivers/mmc/card/block.c
drivers/mmc/core/cd-gpio.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/host.h
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/davinci_mmc.c
drivers/mmc/host/dw_mmc-pci.c [new file with mode: 0644]
drivers/mmc/host/dw_mmc-pltfm.c [new file with mode: 0644]
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h
drivers/mmc/host/mmci.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-spear.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc.h
drivers/mmc/host/tmio_mmc_dma.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mtd/devices/pmc551.c
drivers/mtd/devices/slram.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/nand/bcm_umi_nand.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/net/appletalk/cops.c
drivers/net/appletalk/ltpc.c
drivers/net/arcnet/com20020_cs.c
drivers/net/bonding/bond_main.c
drivers/net/can/slcan.c
drivers/net/cris/eth_v10.c
drivers/net/ethernet/3com/3c574_cs.c
drivers/net/ethernet/3com/3c589_cs.c
drivers/net/ethernet/8390/3c503.c
drivers/net/ethernet/8390/ac3200.c
drivers/net/ethernet/8390/apne.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/axnet_cs.c
drivers/net/ethernet/8390/e2100.c
drivers/net/ethernet/8390/es3210.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/8390/hp-plus.c
drivers/net/ethernet/8390/hp.c
drivers/net/ethernet/8390/lib8390.c
drivers/net/ethernet/8390/lne390.c
drivers/net/ethernet/8390/mac8390.c
drivers/net/ethernet/8390/ne-h8300.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/8390/ne2.c
drivers/net/ethernet/8390/ne2k-pci.c
drivers/net/ethernet/8390/ne3210.c
drivers/net/ethernet/8390/pcnet_cs.c
drivers/net/ethernet/8390/smc-mca.c
drivers/net/ethernet/8390/smc-ultra.c
drivers/net/ethernet/8390/smc-ultra32.c
drivers/net/ethernet/8390/stnic.c
drivers/net/ethernet/8390/wd.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/amd/7990.c
drivers/net/ethernet/amd/am79c961a.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/declance.c
drivers/net/ethernet/amd/hplance.c
drivers/net/ethernet/amd/mvme147.c
drivers/net/ethernet/amd/nmclan_cs.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/cirrus/mac89x0.c
drivers/net/ethernet/dlink/de600.c
drivers/net/ethernet/dlink/de620.c
drivers/net/ethernet/fujitsu/at1700.c
drivers/net/ethernet/fujitsu/eth16i.c
drivers/net/ethernet/fujitsu/fmvj18x_cs.c
drivers/net/ethernet/i825xx/3c507.c
drivers/net/ethernet/i825xx/3c527.c
drivers/net/ethernet/i825xx/eepro.c
drivers/net/ethernet/i825xx/eexpress.c
drivers/net/ethernet/i825xx/ether1.c
drivers/net/ethernet/i825xx/znet.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/micrel/ks8842.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/realtek/atp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/seeq/ether3.c
drivers/net/ethernet/seeq/seeq8005.c
drivers/net/ethernet/smsc/smc91c92_cs.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/hippi/rrunner.c
drivers/net/irda/donauboe.c
drivers/net/loopback.c
drivers/net/plip/plip.c
drivers/net/slip/slhc.c
drivers/net/slip/slip.c
drivers/net/tokenring/3c359.c
drivers/net/tokenring/abyss.c
drivers/net/tokenring/ibmtr_cs.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/madgemc.c
drivers/net/tokenring/olympic.c
drivers/net/tokenring/proteon.c
drivers/net/tokenring/skisa.c
drivers/net/tokenring/smctr.c
drivers/net/tokenring/tms380tr.c
drivers/net/tokenring/tmspci.c
drivers/net/tun.c
drivers/net/wan/dlci.c
drivers/net/wan/dscc4.c
drivers/net/wan/hd64570.c
drivers/net/wan/hd64572.c
drivers/net/wan/lapbether.c
drivers/net/wan/sdla.c
drivers/net/wan/x25_asy.c
drivers/net/wireless/airo.c
drivers/net/wireless/airo_cs.c
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/wl3501_cs.c
drivers/nubus/nubus.c
drivers/of/gpio.c
drivers/parisc/dino.c
drivers/parisc/iosapic.c
drivers/parisc/lba_pci.c
drivers/pcmcia/at91_cf.c
drivers/pcmcia/bcm63xx_pcmcia.c
drivers/pcmcia/bfin_cf_pcmcia.c
drivers/pcmcia/cs.c
drivers/pcmcia/db1xxx_ss.c
drivers/pcmcia/electra_cf.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/pxa2xx_viper.c
drivers/pcmcia/sa11xx_base.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/tcic.c
drivers/pcmcia/vrc4173_cardu.c
drivers/pcmcia/xxs1500_ss.c
drivers/pcmcia/yenta_socket.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/amilo-rfkill.c
drivers/platform/x86/apple-gmux.c [new file with mode: 0644]
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/asus_acpi.c [deleted file]
drivers/platform/x86/compal-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hdaps.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/xo1-rfkill.c
drivers/pnp/pnpbios/bioscalls.c
drivers/pnp/pnpbios/core.c
drivers/rtc/interface.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-sa1100.c
drivers/s390/char/sclp_cmd.c
drivers/s390/cio/crw.c
drivers/s390/crypto/ap_bus.c
drivers/sbus/char/flash.c
drivers/sbus/char/openprom.c
drivers/sbus/char/uctrl.c
drivers/scsi/53c700.c
drivers/scsi/BusLogic.c
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aha1542.c
drivers/scsi/aha1740.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/oak.c
drivers/scsi/atp870u.c
drivers/scsi/dtc.c
drivers/scsi/fd_mcs.c
drivers/scsi/fdomain.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/in2000.c
drivers/scsi/mac53c94.c
drivers/scsi/mac_scsi.c
drivers/scsi/mesh.c
drivers/scsi/ncr53c8xx.c
drivers/scsi/nsp32.c
drivers/scsi/osst.c
drivers/scsi/pas16.c
drivers/scsi/qla1280.c
drivers/scsi/qlogicpti.c
drivers/scsi/st.c
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi_vme.c
drivers/scsi/sym53c416.c
drivers/scsi/t128.c
drivers/scsi/u14-34f.c
drivers/scsi/ultrastor.c
drivers/scsi/wd7000.c
drivers/sh/intc/balancing.c
drivers/sh/intc/core.c
drivers/sh/intc/handle.c
drivers/sh/intc/virq.c
drivers/spi/spi-dw-mid.c
drivers/spi/spi-ep93xx.c
drivers/spi/spi-omap-uwire.c
drivers/spi/spi-pl022.c
drivers/spi/spi-topcliff-pch.c
drivers/staging/android/binder.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/cb_pcidas64.c
drivers/staging/comedi/drivers/mite.c
drivers/staging/crystalhd/bc_dts_defs.h
drivers/staging/crystalhd/crystalhd.h
drivers/staging/crystalhd/crystalhd_lnx.h
drivers/staging/crystalhd/crystalhd_misc.h
drivers/staging/et131x/et131x.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
drivers/staging/media/go7007/go7007-driver.c
drivers/staging/media/go7007/go7007-i2c.c
drivers/staging/media/go7007/go7007-v4l2.c
drivers/staging/media/go7007/snd-go7007.c
drivers/staging/media/lirc/lirc_serial.c
drivers/staging/media/lirc/lirc_sir.c
drivers/staging/mei/wd.c
drivers/staging/panel/panel.c
drivers/staging/sbe-2t3e3/io.c
drivers/staging/telephony/phonedev.c
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/wlags49_h2/wl_cs.c
drivers/staging/wlags49_h2/wl_main.c
drivers/staging/wlags49_h2/wl_netdev.c
drivers/staging/wlags49_h2/wl_pci.c
drivers/staging/wlags49_h2/wl_util.c
drivers/tty/amiserial.c
drivers/tty/hvc/hvc_vio.c
drivers/tty/hvc/hvcs.c
drivers/tty/isicom.c
drivers/tty/moxa.c
drivers/tty/mxser.c
drivers/tty/n_hdlc.c
drivers/tty/n_tty.c
drivers/tty/pty.c
drivers/tty/serial/21285.c
drivers/tty/serial/68328serial.c
drivers/tty/serial/8250/serial_cs.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/crisv10.c
drivers/tty/serial/dz.c
drivers/tty/serial/icom.c
drivers/tty/serial/msm_serial_hs.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sunhv.c
drivers/tty/serial/sunsab.c
drivers/tty/serial/sunsu.c
drivers/tty/serial/sunzilog.c
drivers/tty/serial/zs.c
drivers/tty/synclink.c
drivers/tty/synclink_gt.c
drivers/tty/synclinkmp.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/vt/vt.c
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/langwell_udc.c
drivers/usb/gadget/mv_udc_core.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-hcd.c
drivers/usb/musb/ux500_dma.c
drivers/usb/renesas_usbhs/fifo.c
drivers/video/amifb.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/apple_bl.c
drivers/video/backlight/tosa_lcd.c
drivers/video/bt431.h
drivers/video/bt455.h
drivers/video/console/fbcon.c
drivers/video/console/newport_con.c
drivers/video/cyber2000fb.c
drivers/video/dnfb.c
drivers/video/mx3fb.c
drivers/video/neofb.c
drivers/video/omap2/vrfb.c
drivers/video/pmag-ba-fb.c
drivers/video/pmagb-b-fb.c
drivers/video/q40fb.c
drivers/video/savage/savagefb_driver.c
drivers/virtio/config.c
drivers/watchdog/Kconfig
drivers/watchdog/acquirewdt.c
drivers/watchdog/advantechwdt.c
drivers/watchdog/alim1535_wdt.c
drivers/watchdog/alim7101_wdt.c
drivers/watchdog/ar7_wdt.c
drivers/watchdog/at32ap700x_wdt.c
drivers/watchdog/at91rm9200_wdt.c
drivers/watchdog/at91sam9_wdt.c
drivers/watchdog/ath79_wdt.c
drivers/watchdog/bcm47xx_wdt.c
drivers/watchdog/bcm63xx_wdt.c
drivers/watchdog/bfin_wdt.c
drivers/watchdog/booke_wdt.c
drivers/watchdog/coh901327_wdt.c
drivers/watchdog/cpu5wdt.c
drivers/watchdog/cpwd.c
drivers/watchdog/dw_wdt.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/eurotechwdt.c
drivers/watchdog/f71808e_wdt.c
drivers/watchdog/gef_wdt.c
drivers/watchdog/geodewdt.c
drivers/watchdog/hpwdt.c
drivers/watchdog/i6300esb.c
drivers/watchdog/iTCO_vendor_support.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/ib700wdt.c
drivers/watchdog/ibmasr.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/indydog.c
drivers/watchdog/intel_scu_watchdog.c
drivers/watchdog/intel_scu_watchdog.h
drivers/watchdog/iop_wdt.c
drivers/watchdog/it8712f_wdt.c
drivers/watchdog/it87_wdt.c
drivers/watchdog/ixp2000_wdt.c
drivers/watchdog/ixp4xx_wdt.c
drivers/watchdog/jz4740_wdt.c
drivers/watchdog/ks8695_wdt.c
drivers/watchdog/lantiq_wdt.c
drivers/watchdog/m54xx_wdt.c
drivers/watchdog/machzwd.c
drivers/watchdog/max63xx_wdt.c
drivers/watchdog/mixcomwd.c
drivers/watchdog/mpc8xxx_wdt.c
drivers/watchdog/mpcore_wdt.c
drivers/watchdog/mv64x60_wdt.c
drivers/watchdog/nuc900_wdt.c
drivers/watchdog/nv_tco.c
drivers/watchdog/octeon-wdt-main.c
drivers/watchdog/of_xilinx_wdt.c
drivers/watchdog/omap_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/pc87413_wdt.c
drivers/watchdog/pcwd.c
drivers/watchdog/pcwd_pci.c
drivers/watchdog/pcwd_usb.c
drivers/watchdog/pika_wdt.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/pnx833x_wdt.c
drivers/watchdog/rc32434_wdt.c
drivers/watchdog/riowd.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sa1100_wdt.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/sbc60xxwdt.c
drivers/watchdog/sbc7240_wdt.c
drivers/watchdog/sbc8360.c
drivers/watchdog/sbc_epx_c3.c
drivers/watchdog/sbc_fitpc2_wdt.c
drivers/watchdog/sc1200wdt.c
drivers/watchdog/sc520_wdt.c
drivers/watchdog/sch311x_wdt.c
drivers/watchdog/scx200_wdt.c
drivers/watchdog/shwdt.c
drivers/watchdog/smsc37b787_wdt.c
drivers/watchdog/softdog.c
drivers/watchdog/sp5100_tco.c
drivers/watchdog/sp805_wdt.c
drivers/watchdog/stmp3xxx_wdt.c
drivers/watchdog/ts72xx_wdt.c
drivers/watchdog/twl4030_wdt.c
drivers/watchdog/txx9wdt.c
drivers/watchdog/via_wdt.c
drivers/watchdog/w83627hf_wdt.c
drivers/watchdog/w83697hf_wdt.c
drivers/watchdog/w83697ug_wdt.c
drivers/watchdog/w83877f_wdt.c
drivers/watchdog/w83977f_wdt.c
drivers/watchdog/wafer5823wdt.c
drivers/watchdog/watchdog_core.c
drivers/watchdog/watchdog_dev.c
drivers/watchdog/wdrtas.c
drivers/watchdog/wdt.c
drivers/watchdog/wdt285.c
drivers/watchdog/wdt977.c
drivers/watchdog/wdt_pci.c
drivers/watchdog/wm831x_wdt.c
drivers/watchdog/wm8350_wdt.c
drivers/watchdog/xen_wdt.c
fs/autofs4/dev-ioctl.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/buffer.c
fs/coda/inode.c
fs/coda/psdev.c
fs/coda/upcall.c
fs/compat.c
fs/eventpoll.c
fs/exec.c
fs/exofs/super.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/hash.c
fs/ext4/page-io.c
fs/fcntl.c
fs/file.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/lockd/svc.c
fs/ncpfs/file.c
fs/ncpfs/inode.c
fs/ncpfs/mmap.c
fs/nfs/client.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/getroot.c
fs/nfs/inode.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfsd/current_stateid.h [new file with mode: 0644]
fs/nfsd/export.c
fs/nfsd/netns.h [new file with mode: 0644]
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfssvc.c
fs/nfsd/state.h
fs/nfsd/vfs.c
fs/nfsd/vfs.h
fs/nfsd/xdr4.h
fs/open.c
fs/proc/array.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/namespaces.c
fs/proc/task_mmu.c
fs/reiserfs/journal.c
fs/select.c
fs/squashfs/block.c
fs/squashfs/dir.c
fs/squashfs/namei.c
fs/squashfs/squashfs_fs.h
fs/squashfs/super.c
fs/ufs/inode.c
fs/ufs/super.c
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
include/acpi/platform/aclinux.h
include/asm-generic/atomic.h
include/asm-generic/barrier.h [new file with mode: 0644]
include/asm-generic/bitops/atomic.h
include/asm-generic/cmpxchg.h
include/asm-generic/exec.h [new file with mode: 0644]
include/asm-generic/gpio.h
include/asm-generic/posix_types.h
include/asm-generic/switch_to.h [new file with mode: 0644]
include/asm-generic/system.h [deleted file]
include/asm-generic/unistd.h
include/asm-generic/vmlinux.lds.h
include/linux/Kbuild
include/linux/acpi.h
include/linux/aio_abi.h
include/linux/amba/pl08x.h
include/linux/amba/pl330.h
include/linux/apple_bl.h [new file with mode: 0644]
include/linux/cnt32_to_63.h
include/linux/compat.h
include/linux/cpumask.h
include/linux/cpuset.h
include/linux/debug_locks.h
include/linux/dma-buf.h
include/linux/dma-mapping.h
include/linux/dmaengine.h
include/linux/dw_dmac.h
include/linux/edac.h
include/linux/efi.h
include/linux/fdtable.h
include/linux/fs.h
include/linux/gpio.h
include/linux/i2c-algo-bit.h
include/linux/i2c-algo-pcf.h
include/linux/i2c-dev.h
include/linux/i2c-mux.h
include/linux/i2c-smbus.h
include/linux/i2c.h
include/linux/i2c/twl.h
include/linux/ide.h
include/linux/interrupt.h
include/linux/kernel.h
include/linux/kvm.h
include/linux/kvm_host.h
include/linux/llist.h
include/linux/lsm_audit.h
include/linux/mfd/88pm860x.h
include/linux/mfd/abx500.h
include/linux/mfd/abx500/ab8500-gpio.h
include/linux/mfd/abx500/ab8500-sysctrl.h
include/linux/mfd/abx500/ab8500.h
include/linux/mfd/anatop.h [new file with mode: 0644]
include/linux/mfd/da9052/da9052.h
include/linux/mfd/db8500-prcmu.h
include/linux/mfd/dbx500-prcmu.h
include/linux/mfd/mc13xxx.h
include/linux/mfd/rc5t583.h [new file with mode: 0644]
include/linux/mfd/stmpe.h
include/linux/mfd/tmio.h
include/linux/mfd/tps65090.h [new file with mode: 0644]
include/linux/mfd/tps65217.h [new file with mode: 0644]
include/linux/mfd/tps65910.h
include/linux/mfd/wm8994/pdata.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/mmc/cd-gpio.h
include/linux/mmc/core.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmc/sdhci.h
include/linux/mmc/sh_mmcif.h
include/linux/mmc/sh_mobile_sdhi.h
include/linux/module.h
include/linux/moduleparam.h
include/linux/mtd/map.h
include/linux/nfs4.h
include/linux/nfsd/cld.h [new file with mode: 0644]
include/linux/of.h
include/linux/of_gpio.h
include/linux/parport.h
include/linux/pid_namespace.h
include/linux/radix-tree.h
include/linux/regulator/ab8500.h
include/linux/rtc.h
include/linux/rwsem.h
include/linux/sched.h
include/linux/sh_intc.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/slub_def.h
include/linux/smp.h
include/linux/spinlock.h
include/linux/spinlock_api_smp.h
include/linux/stop_machine.h
include/linux/sunrpc/svc_rdma.h
include/linux/swap.h
include/linux/sysinfo.h [new file with mode: 0644]
include/linux/time.h
include/linux/timex.h
include/linux/tty.h
include/linux/wait.h
include/linux/watchdog.h
include/xen/xen-ops.h
init/main.c
ipc/compat.c
kernel/Kconfig.locks
kernel/Kconfig.preempt
kernel/compat.c
kernel/cpuset.c
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_bt.c
kernel/dma.c
kernel/exit.c
kernel/irq/Kconfig
kernel/irq/irqdomain.c
kernel/kexec.c
kernel/module.c
kernel/params.c
kernel/pid_namespace.c
kernel/rwsem.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/signal.c
kernel/smp.c
kernel/spinlock.c
kernel/sys.c
kernel/sysctl.c
kernel/time.c
kernel/time/alarmtimer.c
kernel/time/clocksource.c
kernel/time/ntp.c
kernel/time/timekeeping.c
lib/Kconfig
lib/Kconfig.debug
lib/cpumask.c
lib/llist.c
lib/radix-tree.c
lib/raid6/altivec.uc
mm/filemap.c
mm/memcontrol.c
mm/page_alloc.c
mm/slab.c
mm/slub.c
mm/swapfile.c
mm/truncate.c
net/802/fc.c
net/802/fddi.c
net/802/hippi.c
net/802/tr.c
net/atm/clip.c
net/ax25/af_ax25.c
net/ax25/ax25_addr.c
net/ax25/ax25_dev.c
net/ax25/ax25_ds_in.c
net/ax25/ax25_ds_subr.c
net/ax25/ax25_ds_timer.c
net/ax25/ax25_iface.c
net/ax25/ax25_in.c
net/ax25/ax25_ip.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_std_in.c
net/ax25/ax25_std_subr.c
net/ax25/ax25_std_timer.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/ax25/ax25_uid.c
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/l2cap_core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/compat.c
net/core/datagram.c
net/core/dev.c
net/core/filter.c
net/core/gen_estimator.c
net/core/rtnetlink.c
net/core/scm.c
net/core/skbuff.c
net/core/sock.c
net/core/utils.c
net/decnet/af_decnet.c
net/decnet/dn_dev.c
net/decnet/dn_nsp_in.c
net/decnet/dn_nsp_out.c
net/econet/af_econet.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/udp.c
net/ipv6/af_inet6.c
net/ipv6/icmp.c
net/ipv6/ip6mr.c
net/irda/irlan/irlan_client.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_provider.c
net/irda/timer.c
net/lapb/lapb_iface.c
net/lapb/lapb_in.c
net/lapb/lapb_out.c
net/lapb/lapb_subr.c
net/lapb/lapb_timer.c
net/netfilter/ipvs/ip_vs_app.c
net/netfilter/ipvs/ip_vs_proto.c
net/netfilter/nfnetlink.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_out.c
net/netrom/nr_route.c
net/netrom/nr_subr.c
net/netrom/nr_timer.c
net/openvswitch/datapath.c
net/packet/af_packet.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/rose/rose_in.c
net/rose/rose_link.c
net/rose/rose_out.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/rose/rose_timer.c
net/socket.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/svc_rdma.c
net/sunrpc/xprtrdma/svc_rdma_marshal.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtsock.c
scripts/gcc-goto.sh
security/apparmor/domain.c
security/apparmor/file.c
security/selinux/hooks.c
security/selinux/include/avc.h
security/selinux/include/xfrm.h
sound/arm/pxa2xx-ac97-lib.c
sound/arm/pxa2xx-ac97.c
sound/atmel/abdac.c
sound/atmel/ac97c.c
sound/oss/os.h
sound/oss/vidc.c
sound/oss/waveartist.c
sound/pci/asihpi/hpios.h
sound/pci/aw2/aw2-saa7146.c
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/sh/siu_pcm.c
sound/soc/txx9/txx9aclc.c
tools/power/cpupower/Makefile
tools/power/cpupower/bench/Makefile
tools/power/cpupower/debug/i386/Makefile
tools/power/cpupower/debug/x86_64/Makefile
tools/power/cpupower/man/cpupower-frequency-info.1
tools/power/cpupower/man/cpupower-frequency-set.1
tools/power/cpupower/man/cpupower-idle-info.1 [new file with mode: 0644]
tools/power/cpupower/man/cpupower-monitor.1
tools/power/cpupower/utils/cpuidle-info.c
tools/power/cpupower/utils/helpers/amd.c
tools/power/cpupower/utils/helpers/helpers.h
tools/power/cpupower/utils/helpers/pci.c
tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
tools/slub/slabinfo.c [deleted file]
tools/testing/selftests/Makefile
tools/testing/selftests/breakpoints/Makefile
tools/testing/selftests/run_tests [deleted file]
tools/testing/selftests/vm/Makefile [new file with mode: 0644]
tools/testing/selftests/vm/hugepage-mmap.c [new file with mode: 0644]
tools/testing/selftests/vm/hugepage-shm.c [new file with mode: 0644]
tools/testing/selftests/vm/map_hugetlb.c [new file with mode: 0644]
tools/testing/selftests/vm/run_vmtests [new file with mode: 0644]
tools/vm/Makefile [new file with mode: 0644]
tools/vm/page-types.c [new file with mode: 0644]
tools/vm/slabinfo.c [new file with mode: 0644]
virt/kvm/assigned-dev.c
virt/kvm/kvm_main.c

diff --git a/Documentation/ABI/testing/debugfs-olpc b/Documentation/ABI/testing/debugfs-olpc
new file mode 100644 (file)
index 0000000..bd76cc6
--- /dev/null
@@ -0,0 +1,16 @@
+What:          /sys/kernel/debug/olpc-ec/cmd
+Date:          Dec 2011
+KernelVersion: 3.4
+Contact:       devel@lists.laptop.org
+Description:
+
+A generic interface for executing OLPC Embedded Controller commands and
+reading their responses.
+
+To execute a command, write data with the format: CC:N A A A A
+CC is the (hex) command, N is the count of expected reply bytes, and A A A A
+are optional (hex) arguments.
+
+To read the response (if any), read from the generic node after executing
+a command. Hex reply bytes will be returned, *whether or not* they came from
+the immediately previous command.
diff --git a/Documentation/ABI/testing/sysfs-block-dm b/Documentation/ABI/testing/sysfs-block-dm
new file mode 100644 (file)
index 0000000..87ca569
--- /dev/null
@@ -0,0 +1,25 @@
+What:          /sys/block/dm-<num>/dm/name
+Date:          January 2009
+KernelVersion: 2.6.29
+Contact:       dm-devel@redhat.com
+Description:   Device-mapper device name.
+               Read-only string containing mapped device name.
+Users:         util-linux, device-mapper udev rules
+
+What:          /sys/block/dm-<num>/dm/uuid
+Date:          January 2009
+KernelVersion: 2.6.29
+Contact:       dm-devel@redhat.com
+Description:   Device-mapper device UUID.
+               Read-only string containing DM-UUID or empty string
+               if DM-UUID is not set.
+Users:         util-linux, device-mapper udev rules
+
+What:          /sys/block/dm-<num>/dm/suspended
+Date:          June 2009
+KernelVersion: 2.6.31
+Contact:       dm-devel@redhat.com
+Description:   Device-mapper device suspend state.
+               Contains the value 1 while the device is suspended.
+               Otherwise it contains 0. Read-only attribute.
+Users:         util-linux, device-mapper udev rules
index e82e7c2b8f80c4f789d8bbb9a0b67be26e6fa023..678819a3f8bf89e3b43e134979af2fa3f28199fd 100644 (file)
@@ -17,3 +17,21 @@ Description: Some Samsung laptops have different "performance levels"
                Specifically, not all support the "overclock" option,
                and it's still unknown if this value even changes
                anything, other than making the user feel a bit better.
+
+What:          /sys/devices/platform/samsung/battery_life_extender
+Date:          December 1, 2011
+KernelVersion: 3.3
+Contact:       Corentin Chary <corentin.chary@gmail.com>
+Description:   Max battery charge level can be modified, battery cycle
+               life can be extended by reducing the max battery charge
+               level.
+               0 means normal battery mode (100% charge)
+               1 means battery life extender mode (80% charge)
+
+What:          /sys/devices/platform/samsung/usb_charge
+Date:          December 1, 2011
+KernelVersion: 3.3
+Contact:       Corentin Chary <corentin.chary@gmail.com>
+Description:   Use your USB ports to charge devices, even
+               when your laptop is powered off.
+               1 means enabled, 0 means disabled.
index 9b4bc5c76f335341d568062d1f4034ec530458a7..30b656ece7aaed21076daa92d865ad472f607e22 100644 (file)
@@ -1,3 +1,3 @@
 obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
        filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
-       pcmcia/ spi/ timers/ vm/ watchdog/src/
+       pcmcia/ spi/ timers/ watchdog/src/
index 1ff044d87ca40d72565191615bac227ee2bc8d5c..3370bc4d7b9885b45040b359d858f4112418b74f 100644 (file)
@@ -75,10 +75,12 @@ less sharing than average you'll need a larger-than-average metadata device.
 
 As a guide, we suggest you calculate the number of bytes to use in the
 metadata device as 48 * $data_dev_size / $data_block_size but round it up
-to 2MB if the answer is smaller.  The largest size supported is 16GB.
+to 2MB if the answer is smaller.  If you're creating large numbers of
+snapshots which are recording large amounts of change, you may find you
+need to increase this.
 
-If you're creating large numbers of snapshots which are recording large
-amounts of change, you may need find you need to increase this.
+The largest size supported is 16GB: If the device is larger,
+a warning will be issued and the excess space will not be used.
 
 Reloading a pool table
 ----------------------
@@ -167,6 +169,38 @@ ii) Using an internal snapshot.
 
     dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
 
+External snapshots
+------------------
+
+You can use an external _read only_ device as an origin for a
+thinly-provisioned volume.  Any read to an unprovisioned area of the
+thin device will be passed through to the origin.  Writes trigger
+the allocation of new blocks as usual.
+
+One use case for this is VM hosts that want to run guests on
+thinly-provisioned volumes but have the base image on another device
+(possibly shared between many VMs).
+
+You must not write to the origin device if you use this technique!
+Of course, you may write to the thin device and take internal snapshots
+of the thin volume.
+
+i) Creating a snapshot of an external device
+
+  This is the same as creating a thin device.
+  You don't mention the origin at this stage.
+
+    dmsetup message /dev/mapper/pool 0 "create_thin 0"
+
+ii) Using a snapshot of an external device.
+
+  Append an extra parameter to the thin target specifying the origin:
+
+    dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 0 /dev/image"
+
+  N.B. All descendants (internal snapshots) of this snapshot require the
+  same extra origin parameter.
+
 Deactivation
 ------------
 
@@ -189,7 +223,13 @@ i) Constructor
              <low water mark (blocks)> [<number of feature args> [<arg>]*]
 
     Optional feature arguments:
-    - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
+
+      skip_block_zeroing: Skip the zeroing of newly-provisioned blocks.
+
+      ignore_discard: Disable discard support.
+
+      no_discard_passdown: Don't pass discards down to the underlying
+                          data device, but just remove the mapping.
 
     Data block size must be between 64KB (128 sectors) and 1GB
     (2097152 sectors) inclusive.
@@ -237,16 +277,6 @@ iii) Messages
 
        Deletes a thin device.  Irreversible.
 
-    trim <dev id> <new size in sectors>
-
-       Delete mappings from the end of a thin device.  Irreversible.
-       You might want to use this if you're reducing the size of
-       your thinly-provisioned device.  In many cases, due to the
-       sharing of blocks between devices, it is not possible to
-       determine in advance how much space 'trim' will release.  (In
-       future a userspace tool might be able to perform this
-       calculation.)
-
     set_transaction_id <current id> <new id>
 
        Userland volume managers, such as LVM, need a way to
@@ -262,7 +292,7 @@ iii) Messages
 
 i) Constructor
 
-    thin <pool dev> <dev id>
+    thin <pool dev> <dev id> [<external origin dev>]
 
     pool dev:
        the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
@@ -271,6 +301,11 @@ i) Constructor
        the internal device identifier of the device to be
        activated.
 
+    external origin dev:
+       an optional block device outside the pool to be treated as a
+       read-only snapshot origin: reads to unprovisioned areas of the
+       thin target will be mapped to this device.
+
 The pool doesn't store any size against the thin devices.  If you
 load a thin target that is smaller than you've been using previously,
 then you'll have no access to blocks mapped beyond the end.  If you
diff --git a/Documentation/device-mapper/verity.txt b/Documentation/device-mapper/verity.txt
new file mode 100644 (file)
index 0000000..32e4879
--- /dev/null
@@ -0,0 +1,194 @@
+dm-verity
+==========
+
+Device-Mapper's "verity" target provides transparent integrity checking of
+block devices using a cryptographic digest provided by the kernel crypto API.
+This target is read-only.
+
+Construction Parameters
+=======================
+    <version> <dev> <hash_dev> <hash_start>
+    <data_block_size> <hash_block_size>
+    <num_data_blocks> <hash_start_block>
+    <algorithm> <digest> <salt>
+
+<version>
+    This is the version number of the on-disk format.
+
+    0 is the original format used in the Chromium OS.
+       The salt is appended when hashing, digests are stored continuously and
+       the rest of the block is padded with zeros.
+
+    1 is the current format that should be used for new devices.
+       The salt is prepended when hashing and each digest is
+       padded with zeros to the power of two.
+
+<dev>
+    This is the device containing the data the integrity of which needs to be
+    checked.  It may be specified as a path, like /dev/sdaX, or a device number,
+    <major>:<minor>.
+
+<hash_dev>
+    This is the device that that supplies the hash tree data.  It may be
+    specified similarly to the device path and may be the same device.  If the
+    same device is used, the hash_start should be outside of the dm-verity
+    configured device size.
+
+<data_block_size>
+    The block size on a data device.  Each block corresponds to one digest on
+    the hash device.
+
+<hash_block_size>
+    The size of a hash block.
+
+<num_data_blocks>
+    The number of data blocks on the data device.  Additional blocks are
+    inaccessible.  You can place hashes to the same partition as data, in this
+    case hashes are placed after <num_data_blocks>.
+
+<hash_start_block>
+    This is the offset, in <hash_block_size>-blocks, from the start of hash_dev
+    to the root block of the hash tree.
+
+<algorithm>
+    The cryptographic hash algorithm used for this device.  This should
+    be the name of the algorithm, like "sha1".
+
+<digest>
+    The hexadecimal encoding of the cryptographic hash of the root hash block
+    and the salt.  This hash should be trusted as there is no other authenticity
+    beyond this point.
+
+<salt>
+    The hexadecimal encoding of the salt value.
+
+Theory of operation
+===================
+
+dm-verity is meant to be setup as part of a verified boot path.  This
+may be anything ranging from a boot using tboot or trustedgrub to just
+booting from a known-good device (like a USB drive or CD).
+
+When a dm-verity device is configured, it is expected that the caller
+has been authenticated in some way (cryptographic signatures, etc).
+After instantiation, all hashes will be verified on-demand during
+disk access.  If they cannot be verified up to the root node of the
+tree, the root hash, then the I/O will fail.  This should identify
+tampering with any data on the device and the hash data.
+
+Cryptographic hashes are used to assert the integrity of the device on a
+per-block basis.  This allows for a lightweight hash computation on first read
+into the page cache.  Block hashes are stored linearly-aligned to the nearest
+block the size of a page.
+
+Hash Tree
+---------
+
+Each node in the tree is a cryptographic hash.  If it is a leaf node, the hash
+is of some block data on disk.  If it is an intermediary node, then the hash is
+of a number of child nodes.
+
+Each entry in the tree is a collection of neighboring nodes that fit in one
+block.  The number is determined based on block_size and the size of the
+selected cryptographic digest algorithm.  The hashes are linearly-ordered in
+this entry and any unaligned trailing space is ignored but included when
+calculating the parent node.
+
+The tree looks something like:
+
+alg = sha256, num_blocks = 32768, block_size = 4096
+
+                                 [   root    ]
+                                /    . . .    \
+                     [entry_0]                 [entry_1]
+                    /  . . .  \                 . . .   \
+         [entry_0_0]   . . .  [entry_0_127]    . . . .  [entry_1_127]
+           / ... \             /   . . .  \             /           \
+     blk_0 ... blk_127  blk_16256   blk_16383      blk_32640 . . . blk_32767
+
+
+On-disk format
+==============
+
+Below is the recommended on-disk format. The verity kernel code does not
+read the on-disk header. It only reads the hash blocks which directly
+follow the header. It is expected that a user-space tool will verify the
+integrity of the verity_header and then call dmsetup with the correct
+parameters. Alternatively, the header can be omitted and the dmsetup
+parameters can be passed via the kernel command-line in a rooted chain
+of trust where the command-line is verified.
+
+The on-disk format is especially useful in cases where the hash blocks
+are on a separate partition. The magic number allows easy identification
+of the partition contents. Alternatively, the hash blocks can be stored
+in the same partition as the data to be verified. In such a configuration
+the filesystem on the partition would be sized a little smaller than
+the full-partition, leaving room for the hash blocks.
+
+struct superblock {
+       uint8_t signature[8]
+               "verity\0\0";
+
+       uint8_t version;
+               1 - current format
+
+       uint8_t data_block_bits;
+               log2(data block size)
+
+       uint8_t hash_block_bits;
+               log2(hash block size)
+
+       uint8_t pad1[1];
+               zero padding
+
+       uint16_t salt_size;
+               big-endian salt size
+
+       uint8_t pad2[2];
+               zero padding
+
+       uint32_t data_blocks_hi;
+               big-endian high 32 bits of the 64-bit number of data blocks
+
+       uint32_t data_blocks_lo;
+               big-endian low 32 bits of the 64-bit number of data blocks
+
+       uint8_t algorithm[16];
+               cryptographic algorithm
+
+       uint8_t salt[384];
+               salt (the salt size is specified above)
+
+       uint8_t pad3[88];
+               zero padding to 512-byte boundary
+}
+
+Directly following the header (and with sector number padded to the next hash
+block boundary) are the hash blocks which are stored a depth at a time
+(starting from the root), sorted in order of increasing index.
+
+Status
+======
+V (for Valid) is returned if every check performed so far was valid.
+If any check failed, C (for Corruption) is returned.
+
+Example
+=======
+
+Setup a device:
+  dmsetup create vroot --table \
+    "0 2097152 "\
+    "verity 1 /dev/sda1 /dev/sda2 4096 4096 2097152 1 "\
+    "4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 "\
+    "1234000000000000000000000000000000000000000000000000000000000000"
+
+A command line tool veritysetup is available to compute or verify
+the hash tree or activate the kernel driver.  This is available from
+the LVM2 upstream repository and may be supplied as a package called
+device-mapper-verity-tools:
+    git://sources.redhat.com/git/lvm2
+    http://sourceware.org/git/?p=lvm2.git
+    http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/verity?cvsroot=lvm2
+
+veritysetup -a vroot /dev/sda1 /dev/sda2 \
+       4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076
diff --git a/Documentation/devicetree/bindings/gpio/gpio-omap.txt b/Documentation/devicetree/bindings/gpio/gpio-omap.txt
new file mode 100644 (file)
index 0000000..bff51a2
--- /dev/null
@@ -0,0 +1,36 @@
+OMAP GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "ti,omap2-gpio" for OMAP2 controllers
+  - "ti,omap3-gpio" for OMAP3 controllers
+  - "ti,omap4-gpio" for OMAP4 controllers
+- #gpio-cells : Should be two.
+  - first cell is the pin number
+  - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+- interrupt-controller: Mark the device node as an interrupt controller
+  The first cell is the GPIO number.
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+
+OMAP specific properties:
+- ti,hwmods: Name of the hwmod associated to the GPIO:
+  "gpio<X>", <X> being the 1-based instance number from the HW spec
+
+
+Example:
+
+gpio4: gpio4 {
+    compatible = "ti,omap4-gpio";
+    ti,hwmods = "gpio4";
+    #gpio-cells = <2>;
+    gpio-controller;
+    #interrupt-cells = <2>;
+    interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt b/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt
new file mode 100644 (file)
index 0000000..16695d9
--- /dev/null
@@ -0,0 +1,23 @@
+twl4030 GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "ti,twl4030-gpio" for twl4030 GPIO controller
+- #gpio-cells : Should be two.
+  - first cell is the pin number
+  - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+- interrupt-controller: Mark the device node as an interrupt controller
+  The first cell is the GPIO number.
+  The second cell is not used.
+
+Example:
+
+twl_gpio: gpio {
+    compatible = "ti,twl4030-gpio";
+    #gpio-cells = <2>;
+    gpio-controller;
+    #interrupt-cells = <2>;
+    interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/gpio/sodaville.txt b/Documentation/devicetree/bindings/gpio/sodaville.txt
new file mode 100644 (file)
index 0000000..563eff2
--- /dev/null
@@ -0,0 +1,48 @@
+GPIO controller on CE4100 / Sodaville SoCs
+==========================================
+
+The bindings for CE4100's GPIO controller match the generic description
+which is covered by the gpio.txt file in this folder.
+
+The only additional property is the intel,muxctl property which holds the
+value which is written into the MUXCNTL register.
+
+There is no compatible property for now because the driver is probed via
+PCI id (vendor 0x8086 device 0x2e67).
+
+The interrupt specifier consists of two cells encoded as follows:
+ - <1st cell>: The interrupt-number that identifies the interrupt source.
+ - <2nd cell>: The level-sense information, encoded as follows:
+               4 - active high level-sensitive
+               8 - active low level-sensitive
+
+Example of the GPIO device and one user:
+
+       pcigpio: gpio@b,1 {
+                       /* two cells for GPIO and interrupt */
+                       #gpio-cells = <2>;
+                       #interrupt-cells = <2>;
+                       compatible = "pci8086,2e67.2",
+                                          "pci8086,2e67",
+                                          "pciclassff0000",
+                                          "pciclassff00";
+
+                       reg = <0x15900 0x0 0x0 0x0 0x0>;
+                       /* Interrupt line of the gpio device */
+                       interrupts = <15 1>;
+                       /* It is an interrupt and GPIO controller itself */
+                       interrupt-controller;
+                       gpio-controller;
+                       intel,muxctl = <0>;
+       };
+
+       testuser@20 {
+                       compatible = "example,testuser";
+                       /* User the 11th GPIO line as an active high triggered
+                        * level interrupt
+                        */
+                       interrupts = <11 8>;
+                       interrupt-parent = <&pcigpio>;
+                       /* Use this GPIO also with the gpio functions */
+                       gpios = <&pcigpio 11 0>;
+       };
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
new file mode 100644 (file)
index 0000000..dbd4368
--- /dev/null
@@ -0,0 +1,33 @@
+* TI Highspeed MMC host controller for OMAP
+
+The Highspeed MMC Host Controller on TI OMAP family
+provides an interface for MMC, SD, and SDIO types of memory cards.
+
+Required properties:
+- compatible:
+ Should be "ti,omap2-hsmmc", for OMAP2 controllers
+ Should be "ti,omap3-hsmmc", for OMAP3 controllers
+ Should be "ti,omap4-hsmmc", for OMAP4 controllers
+- ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
+- reg : should contain hsmmc registers location and length
+
+Optional properties:
+ti,dual-volt: boolean, supports dual voltage cards
+<supply-name>-supply: phandle to the regulator device tree node
+"supply-name" examples are "vmmc", "vmmc_aux" etc
+ti,bus-width: Number of data lines, default assumed is 1 if the property is missing.
+cd-gpios: GPIOs for card detection
+wp-gpios: GPIOs for write protection
+ti,non-removable: non-removable slot (like eMMC)
+ti,needs-special-reset: Requires a special softreset sequence
+
+Example:
+       mmc1: mmc@0x4809c000 {
+               compatible = "ti,omap4-hsmmc";
+               reg = <0x4809c000 0x400>;
+               ti,hwmods = "mmc1";
+               ti,dual-volt;
+               ti,bus-width = <4>;
+               vmmc-supply = <&vmmc>; /* phandle to regulator node */
+               ti,non-removable;
+       };
index 225f96d88f55e055ff3f3c089f24b5f93d6d275b..3bbd5c51605a39e7726088b792c6ba46385e0152 100644 (file)
@@ -32,8 +32,12 @@ The buffer-user
 *IMPORTANT*: [see https://lkml.org/lkml/2011/12/20/211 for more details]
 For this first version, A buffer shared using the dma_buf sharing API:
 - *may* be exported to user space using "mmap" *ONLY* by exporter, outside of
-   this framework.
-- may be used *ONLY* by importers that do not need CPU access to the buffer.
+  this framework.
+- with this new iteration of the dma-buf api cpu access from the kernel has been
+  enable, see below for the details.
+
+dma-buf operations for device dma only
+--------------------------------------
 
 The dma_buf buffer sharing API usage contains the following steps:
 
@@ -219,10 +223,120 @@ NOTES:
    If the exporter chooses not to allow an attach() operation once a
    map_dma_buf() API has been called, it simply returns an error.
 
-Miscellaneous notes:
+Kernel cpu access to a dma-buf buffer object
+--------------------------------------------
+
+The motivation to allow cpu access from the kernel to a dma-buf object from the
+importers side are:
+- fallback operations, e.g. if the devices is connected to a usb bus and the
+  kernel needs to shuffle the data around first before sending it away.
+- full transparency for existing users on the importer side, i.e. userspace
+  should not notice the difference between a normal object from that subsystem
+  and an imported one backed by a dma-buf. This is really important for drm
+  opengl drivers that expect to still use all the existing upload/download
+  paths.
+
+Access to a dma_buf from the kernel context involves three steps:
+
+1. Prepare access, which invalidate any necessary caches and make the object
+   available for cpu access.
+2. Access the object page-by-page with the dma_buf map apis
+3. Finish access, which will flush any necessary cpu caches and free reserved
+   resources.
+
+1. Prepare access
+
+   Before an importer can access a dma_buf object with the cpu from the kernel
+   context, it needs to notify the exporter of the access that is about to
+   happen.
+
+   Interface:
+      int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+                                  size_t start, size_t len,
+                                  enum dma_data_direction direction)
+
+   This allows the exporter to ensure that the memory is actually available for
+   cpu access - the exporter might need to allocate or swap-in and pin the
+   backing storage. The exporter also needs to ensure that cpu access is
+   coherent for the given range and access direction. The range and access
+   direction can be used by the exporter to optimize the cache flushing, i.e.
+   access outside of the range or with a different direction (read instead of
+   write) might return stale or even bogus data (e.g. when the exporter needs to
+   copy the data to temporary storage).
+
+   This step might fail, e.g. in oom conditions.
+
+2. Accessing the buffer
+
+   To support dma_buf objects residing in highmem cpu access is page-based using
+   an api similar to kmap. Accessing a dma_buf is done in aligned chunks of
+   PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which returns
+   a pointer in kernel virtual address space. Afterwards the chunk needs to be
+   unmapped again. There is no limit on how often a given chunk can be mapped
+   and unmapped, i.e. the importer does not need to call begin_cpu_access again
+   before mapping the same chunk again.
+
+   Interfaces:
+      void *dma_buf_kmap(struct dma_buf *, unsigned long);
+      void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
+
+   There are also atomic variants of these interfaces. Like for kmap they
+   facilitate non-blocking fast-paths. Neither the importer nor the exporter (in
+   the callback) is allowed to block when using these.
+
+   Interfaces:
+      void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
+      void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
+
+   For importers all the restrictions of using kmap apply, like the limited
+   supply of kmap_atomic slots. Hence an importer shall only hold onto at most 2
+   atomic dma_buf kmaps at the same time (in any given process context).
+
+   dma_buf kmap calls outside of the range specified in begin_cpu_access are
+   undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on
+   the partial chunks at the beginning and end but may return stale or bogus
+   data outside of the range (in these partial chunks).
+
+   Note that these calls need to always succeed. The exporter needs to complete
+   any preparations that might fail in begin_cpu_access.
+
+3. Finish access
+
+   When the importer is done accessing the range specified in begin_cpu_access,
+   it needs to announce this to the exporter (to facilitate cache flushing and
+   unpinning of any pinned resources). The result of of any dma_buf kmap calls
+   after end_cpu_access is undefined.
+
+   Interface:
+      void dma_buf_end_cpu_access(struct dma_buf *dma_buf,
+                                 size_t start, size_t len,
+                                 enum dma_data_direction dir);
+
+
+Miscellaneous notes
+-------------------
+
 - Any exporters or users of the dma-buf buffer sharing framework must have
   a 'select DMA_SHARED_BUFFER' in their respective Kconfigs.
 
+- In order to avoid fd leaks on exec, the FD_CLOEXEC flag must be set
+  on the file descriptor.  This is not just a resource leak, but a
+  potential security hole.  It could give the newly exec'd application
+  access to buffers, via the leaked fd, to which it should otherwise
+  not be permitted access.
+
+  The problem with doing this via a separate fcntl() call, versus doing it
+  atomically when the fd is created, is that this is inherently racy in a
+  multi-threaded app[3].  The issue is made worse when it is library code
+  opening/creating the file descriptor, as the application may not even be
+  aware of the fd's.
+
+  To avoid this problem, userspace must have a way to request O_CLOEXEC
+  flag be set when the dma-buf fd is created.  So any API provided by
+  the exporting driver to create a dmabuf fd must provide a way to let
+  userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd().
+
 References:
 [1] struct dma_buf_ops in include/linux/dma-buf.h
 [2] All interfaces mentioned above defined in include/linux/dma-buf.h
+[3] https://lwn.net/Articles/236486/
index ac2facc50d2a2b2914d10a3268c3ae375ae57d6c..46dfc6b038c3fd57892e272de065e51a025c64f3 100644 (file)
@@ -113,8 +113,8 @@ the fdtable structure -
        if (fd >= 0) {
                /* locate_fd() may have expanded fdtable, load the ptr */
                fdt = files_fdtable(files);
-               FD_SET(fd, fdt->open_fds);
-               FD_CLR(fd, fdt->close_on_exec);
+               __set_open_fd(fd, fdt);
+               __clear_close_on_exec(fd, fdt);
                spin_unlock(&files->file_lock);
        .....
 
index 792faa3c06cf7ccda5ab081dbf568276324538e5..620a07844e8cee6af9fe7415c7cd016766252250 100644 (file)
@@ -271,9 +271,26 @@ Some platforms may also use knowledge about what GPIOs are active for
 power management, such as by powering down unused chip sectors and, more
 easily, gating off unused clocks.
 
-Note that requesting a GPIO does NOT cause it to be configured in any
-way; it just marks that GPIO as in use.  Separate code must handle any
-pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
+For GPIOs that use pins known to the pinctrl subsystem, that subsystem should
+be informed of their use; a gpiolib driver's .request() operation may call
+pinctrl_request_gpio(), and a gpiolib driver's .free() operation may call
+pinctrl_free_gpio(). The pinctrl subsystem allows a pinctrl_request_gpio()
+to succeed concurrently with a pin or pingroup being "owned" by a device for
+pin multiplexing.
+
+Any programming of pin multiplexing hardware that is needed to route the
+GPIO signal to the appropriate pin should occur within a GPIO driver's
+.direction_input() or .direction_output() operations, and occur after any
+setup of an output GPIO's value. This allows a glitch-free migration from a
+pin's special function to GPIO. This is sometimes required when using a GPIO
+to implement a workaround on signals typically driven by a non-GPIO HW block.
+
+Some platforms allow some or all GPIO signals to be routed to different pins.
+Similarly, other aspects of the GPIO or pin may need to be configured, such as
+pullup/pulldown. Platform software should arrange that any such details are
+configured prior to gpio_request() being called for those GPIOs, e.g. using
+the pinctrl subsystem's mapping table, so that GPIO users need not be aware
+of these details.
 
 Also note that it's your responsibility to have stopped using a GPIO
 before you free it.
@@ -302,6 +319,8 @@ where 'flags' is currently defined to specify the following properties:
 
        * GPIOF_INIT_LOW        - as output, set initial level to LOW
        * GPIOF_INIT_HIGH       - as output, set initial level to HIGH
+       * GPIOF_OPEN_DRAIN      - gpio pin is open drain type.
+       * GPIOF_OPEN_SOURCE     - gpio pin is open source type.
 
 since GPIOF_INIT_* are only valid when configured as output, so group valid
 combinations as:
@@ -310,8 +329,19 @@ combinations as:
        * GPIOF_OUT_INIT_LOW    - configured as output, initial level LOW
        * GPIOF_OUT_INIT_HIGH   - configured as output, initial level HIGH
 
-In the future, these flags can be extended to support more properties such
-as open-drain status.
+When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is
+open drain type. Such pins will not be driven to 1 in output mode. It is
+require to connect pull-up on such pins. By enabling this flag, gpio lib will
+make the direction to input when it is asked to set value of 1 in output mode
+to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode.
+
+When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is
+open source type. Such pins will not be driven to 0 in output mode. It is
+require to connect pull-down on such pin. By enabling this flag, gpio lib will
+make the direction to input when it is asked to set value of 0 in output mode
+to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode.
+
+In the future, these flags can be extended to support more properties.
 
 Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
 introduced to encapsulate all three fields as:
index 2871fd5003492b1d3ba266e2cd65aec8ebd58406..71f55bbcefc811e2d78b2987744405c3172314b3 100644 (file)
@@ -20,6 +20,7 @@ Supported adapters:
   * Intel Patsburg (PCH)
   * Intel DH89xxCC (PCH)
   * Intel Panther Point (PCH)
+  * Intel Lynx Point (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index 58eac231fe694649e493aac00b8510028233cfa0..c1601e5a8b71e81ae57f7d1d5a70be5449501443 100644 (file)
@@ -1699,6 +1699,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        The default is to send the implementation identification
                        information.
 
+       nfsd.nfs4_disable_idmapping=
+                       [NFSv4] When set to the default of '1', the NFSv4
+                       server will return only numeric uids and gids to
+                       clients using auth_sys, and will accept numeric uids
+                       and gids from such clients.  This is intended to ease
+                       migration from NFSv2/v3.
 
        objlayoutdriver.osd_login_prog=
                        [NFS] [OBJLAYOUT] sets the pathname to the program which
@@ -1869,6 +1875,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        shutdown the other cpus.  Instead use the REBOOT_VECTOR
                        irq.
 
+       nomodule        Disable module load
+
        nopat           [X86] Disable PAT (page attribute table extension of
                        pagetables) support.
 
index 803e51f6768b65d6bb8a02f4914f0b98e563ef79..a1e04d679289beaca490b272b75c68e3a687a261 100644 (file)
@@ -45,7 +45,7 @@ Status
 Usage
 -----
 
-  Try "modprobe asus_acpi". Check your dmesg (simply type dmesg). You should
+  Try "modprobe asus-laptop". Check your dmesg (simply type dmesg). You should
   see some lines like this :
 
       Asus Laptop Extras version 0.42
index 2bd4e82e5d9ff2085f78f44c6a9351a61a2512e5..0d5ac7f5287e611d4aa171937a1d83b31d0f6038 100644 (file)
@@ -17,6 +17,11 @@ subsystem. See the logs of acpid or /proc/acpi/event and
 devices are created by the driver. Additionally, loading the driver with the
 debug option will report all events in the kernel log.
 
+The "scancodes" passed to the input system (that can be remapped with udev)
+are indexes to the table "sony_laptop_input_keycode_map" in the sony-laptop.c
+module.  For example the "FN/E" key combination (EJECTCD on some models)
+generates the scancode 20 (0x14).
+
 Backlight control:
 ------------------
 If your laptop model supports it, you will find sysfs files in the
index e1d94bf4056e77ab6df7dbc6d9c72b35f183190a..6386f8c0482eaa578f68dfe850e559691e9de95d 100644 (file)
@@ -95,7 +95,7 @@ described as 'basic' will be available.
 Capability: basic
 Architectures: all
 Type: system ioctl
-Parameters: none
+Parameters: machine type identifier (KVM_VM_*)
 Returns: a VM fd that can be used to control the new virtual machine.
 
 The new VM has no virtual cpus and no memory.  An mmap() of a VM fd
@@ -103,6 +103,11 @@ will access the virtual machine's physical address space; offset zero
 corresponds to guest physical address zero.  Use of mmap() on a VM fd
 is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is
 available.
+You most certainly want to use 0 as machine type.
+
+In order to create user controlled virtual machines on S390, check
+KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
+privileged user (CAP_SYS_ADMIN).
 
 4.3 KVM_GET_MSR_INDEX_LIST
 
@@ -213,6 +218,11 @@ allocation of vcpu ids.  For example, if userspace wants
 single-threaded guest vcpus, it should make all vcpu ids be a multiple
 of the number of vcpus per vcore.
 
+For virtual cpus that have been created with S390 user controlled virtual
+machines, the resulting vcpu fd can be memory mapped at page offset
+KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
+cpu's hardware control block.
+
 4.8 KVM_GET_DIRTY_LOG (vm ioctl)
 
 Capability: basic
@@ -1159,6 +1169,14 @@ following flags are specified:
 
 /* Depends on KVM_CAP_IOMMU */
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
+/* The following two depend on KVM_CAP_PCI_2_3 */
+#define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
+#define KVM_DEV_ASSIGN_MASK_INTX       (1 << 2)
+
+If KVM_DEV_ASSIGN_PCI_2_3 is set, the kernel will manage legacy INTx interrupts
+via the PCI-2.3-compliant device-level mask, thus enable IRQ sharing with other
+assigned devices or host devices. KVM_DEV_ASSIGN_MASK_INTX specifies the
+guest's view on the INTx mask, see KVM_ASSIGN_SET_INTX_MASK for details.
 
 The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure
 isolation of the device.  Usages not specifying this flag are deprecated.
@@ -1399,6 +1417,71 @@ The following flags are defined:
 If datamatch flag is set, the event will be signaled only if the written value
 to the registered address is equal to datamatch in struct kvm_ioeventfd.
 
+4.59 KVM_DIRTY_TLB
+
+Capability: KVM_CAP_SW_TLB
+Architectures: ppc
+Type: vcpu ioctl
+Parameters: struct kvm_dirty_tlb (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+This must be called whenever userspace has changed an entry in the shared
+TLB, prior to calling KVM_RUN on the associated vcpu.
+
+The "bitmap" field is the userspace address of an array.  This array
+consists of a number of bits, equal to the total number of TLB entries as
+determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
+nearest multiple of 64.
+
+Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
+array.
+
+The array is little-endian: the bit 0 is the least significant bit of the
+first byte, bit 8 is the least significant bit of the second byte, etc.
+This avoids any complications with differing word sizes.
+
+The "num_dirty" field is a performance hint for KVM to determine whether it
+should skip processing the bitmap and just invalidate everything.  It must
+be set to the number of set bits in the bitmap.
+
+4.60 KVM_ASSIGN_SET_INTX_MASK
+
+Capability: KVM_CAP_PCI_2_3
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_assigned_pci_dev (in)
+Returns: 0 on success, -1 on error
+
+Allows userspace to mask PCI INTx interrupts from the assigned device.  The
+kernel will not deliver INTx interrupts to the guest between setting and
+clearing of KVM_ASSIGN_SET_INTX_MASK via this interface.  This enables use of
+and emulation of PCI 2.3 INTx disable command register behavior.
+
+This may be used for both PCI 2.3 devices supporting INTx disable natively and
+older devices lacking this support. Userspace is responsible for emulating the
+read value of the INTx disable bit in the guest visible PCI command register.
+When modifying the INTx disable state, userspace should precede updating the
+physical device command register by calling this ioctl to inform the kernel of
+the new intended INTx mask state.
+
+Note that the kernel uses the device INTx disable bit to internally manage the
+device interrupt state for PCI 2.3 devices.  Reads of this register may
+therefore not match the expected value.  Writes should always use the guest
+intended INTx disable value rather than attempting to read-copy-update the
+current physical device state.  Races between user and kernel updates to the
+INTx disable bit are handled lazily in the kernel.  It's possible the device
+may generate unintended interrupts, but they will not be injected into the
+guest.
+
+See KVM_ASSIGN_DEV_IRQ for the data structure.  The target device is specified
+by assigned_dev_id.  In the flags field, only KVM_DEV_ASSIGN_MASK_INTX is
+evaluated.
+
 4.62 KVM_CREATE_SPAPR_TCE
 
 Capability: KVM_CAP_SPAPR_TCE
@@ -1491,6 +1574,101 @@ following algorithm:
 Some guests configure the LINT1 NMI input to cause a panic, aiding in
 debugging.
 
+4.65 KVM_S390_UCAS_MAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl maps the memory at "user_addr" with the length "length" to
+the vcpu's address space starting at "vcpu_addr". All parameters need to
+be alligned by 1 megabyte.
+
+4.66 KVM_S390_UCAS_UNMAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl unmaps the memory in the vcpu's address space starting at
+"vcpu_addr" with the length "length". The field "user_addr" is ignored.
+All parameters need to be alligned by 1 megabyte.
+
+4.67 KVM_S390_VCPU_FAULT
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: vcpu absolute address (in)
+Returns: 0 in case of success
+
+This call creates a page table entry on the virtual cpu's address space
+(for user controlled virtual machines) or the virtual machine's address
+space (for regular virtual machines). This only works for minor faults,
+thus it's recommended to access subject memory page via the user page
+table upfront. This is useful to handle validity intercepts for user
+controlled virtual machines to fault in the virtual cpu's lowcore pages
+prior to calling the KVM_RUN ioctl.
+
+4.68 KVM_SET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in)
+Returns: 0 on success, negative value on failure
+
+struct kvm_one_reg {
+       __u64 id;
+       __u64 addr;
+};
+
+Using this ioctl, a single vcpu register can be set to a specific value
+defined by user space with the passed in struct kvm_one_reg, where id
+refers to the register identifier as described below and addr is a pointer
+to a variable with the respective size. There can be architecture agnostic
+and architecture specific registers. Each have their own range of operation
+and their own constants and width. To keep track of the implemented
+registers, find a list below:
+
+  Arch  |       Register        | Width (bits)
+        |                       |
+  PPC   | KVM_REG_PPC_HIOR      | 64
+
+4.69 KVM_GET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in and out)
+Returns: 0 on success, negative value on failure
+
+This ioctl allows to receive the value of a single register implemented
+in a vcpu. The register to read is indicated by the "id" field of the
+kvm_one_reg struct passed in. On success, the register value can be found
+at the memory location pointed to by "addr".
+
+The list of registers accessible using this interface is identical to the
+list in 4.64.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
@@ -1651,6 +1829,20 @@ s390 specific.
 
 s390 specific.
 
+               /* KVM_EXIT_S390_UCONTROL */
+               struct {
+                       __u64 trans_exc_code;
+                       __u32 pgm_code;
+               } s390_ucontrol;
+
+s390 specific. A page fault has occurred for a user controlled virtual
+machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
+resolved by the kernel.
+The program code and the translation exception code that were placed
+in the cpu's lowcore are presented here as defined by the z Architecture
+Principles of Operation Book in the Chapter for Dynamic Address Translation
+(DAT)
+
                /* KVM_EXIT_DCR */
                struct {
                        __u32 dcrn;
@@ -1693,6 +1885,29 @@ developer registration required to access it).
                /* Fix the size of the union. */
                char padding[256];
        };
+
+       /*
+        * shared registers between kvm and userspace.
+        * kvm_valid_regs specifies the register classes set by the host
+        * kvm_dirty_regs specified the register classes dirtied by userspace
+        * struct kvm_sync_regs is architecture specific, as well as the
+        * bits for kvm_valid_regs and kvm_dirty_regs
+        */
+       __u64 kvm_valid_regs;
+       __u64 kvm_dirty_regs;
+       union {
+               struct kvm_sync_regs regs;
+               char padding[1024];
+       } s;
+
+If KVM_CAP_SYNC_REGS is defined, these fields allow userspace to access
+certain guest registers without having to call SET/GET_*REGS. Thus we can
+avoid some system call overhead if userspace has to handle the exit.
+Userspace can query the validity of the structure by checking
+kvm_valid_regs for specific bits. These bits are architecture specific
+and usually define the validity of a groups of registers. (e.g. one bit
+ for general purpose registers)
+
 };
 
 6. Capabilities that can be enabled
@@ -1741,3 +1956,45 @@ HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
 HTAB invisible to the guest.
 
 When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
+
+6.3 KVM_CAP_SW_TLB
+
+Architectures: ppc
+Parameters: args[0] is the address of a struct kvm_config_tlb
+Returns: 0 on success; -1 on error
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+Configures the virtual CPU's TLB array, establishing a shared memory area
+between userspace and KVM.  The "params" and "array" fields are userspace
+addresses of mmu-type-specific data structures.  The "array_len" field is an
+safety mechanism, and should be set to the size in bytes of the memory that
+userspace has reserved for the array.  It must be at least the size dictated
+by "mmu_type" and "params".
+
+While KVM_RUN is active, the shared region is under control of KVM.  Its
+contents are undefined, and any modification by userspace results in
+boundedly undefined behavior.
+
+On return from KVM_RUN, the shared region will reflect the current state of
+the guest's TLB.  If userspace makes any changes, it must call KVM_DIRTY_TLB
+to tell KVM which entries have been changed, prior to calling KVM_RUN again
+on this vcpu.
+
+For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+ - The "params" field is of type "struct kvm_book3e_206_tlb_params".
+ - The "array" field points to an array of type "struct
+   kvm_book3e_206_tlb_entry".
+ - The array consists of all entries in the first TLB, followed by all
+   entries in the second TLB.
+ - Within a TLB, entries are ordered first by increasing set number.  Within a
+   set, entries are ordered by way (increasing ESEL).
+ - The hash for determining set number in TLB0 is: (MAS2 >> 12) & (num_sets - 1)
+   where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
+ - The tsize field of mas1 shall be set to 4K on TLB0, even though the
+   hardware ignores this value for TLB0.
index 2b7ce190cde47041edfebbb66a6dc853327e8549..6e7c370509304e61b272043ad91f35b2c6328c8e 100644 (file)
@@ -81,28 +81,8 @@ additional registers to the magic page. If you add fields to the magic page,
 also define a new hypercall feature to indicate that the host can give you more
 registers. Only if the host supports the additional features, make use of them.
 
-The magic page has the following layout as described in
-arch/powerpc/include/asm/kvm_para.h:
-
-struct kvm_vcpu_arch_shared {
-       __u64 scratch1;
-       __u64 scratch2;
-       __u64 scratch3;
-       __u64 critical;         /* Guest may not get interrupts if == r1 */
-       __u64 sprg0;
-       __u64 sprg1;
-       __u64 sprg2;
-       __u64 sprg3;
-       __u64 srr0;
-       __u64 srr1;
-       __u64 dar;
-       __u64 msr;
-       __u32 dsisr;
-       __u32 int_pending;      /* Tells the guest if we have an interrupt */
-};
-
-Additions to the page must only occur at the end. Struct fields are always 32
-or 64 bit aligned, depending on them being 32 or 64 bit wide respectively.
+The magic page layout is described by struct kvm_vcpu_arch_shared
+in arch/powerpc/include/asm/kvm_para.h.
 
 Magic page features
 ===================
diff --git a/Documentation/vm/Makefile b/Documentation/vm/Makefile
deleted file mode 100644 (file)
index 3fa4d06..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# kbuild trick to avoid linker error. Can be omitted if a module is built.
-obj- := dummy.o
-
-# List of programs to build
-hostprogs-y := page-types hugepage-mmap hugepage-shm map_hugetlb
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
diff --git a/Documentation/vm/hugepage-mmap.c b/Documentation/vm/hugepage-mmap.c
deleted file mode 100644 (file)
index db0dd9a..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * hugepage-mmap:
- *
- * Example of using huge page memory in a user application using the mmap
- * system call.  Before running this application, make sure that the
- * administrator has mounted the hugetlbfs filesystem (on some directory
- * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
- * example, the app is requesting memory of size 256MB that is backed by
- * huge pages.
- *
- * For the ia64 architecture, the Linux kernel reserves Region number 4 for
- * huge pages.  That means that if one requires a fixed address, a huge page
- * aligned address starting with 0x800000... will be required.  If a fixed
- * address is not required, the kernel will select an address in the proper
- * range.
- * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-
-#define FILE_NAME "/mnt/hugepagefile"
-#define LENGTH (256UL*1024*1024)
-#define PROTECTION (PROT_READ | PROT_WRITE)
-
-/* Only ia64 requires this */
-#ifdef __ia64__
-#define ADDR (void *)(0x8000000000000000UL)
-#define FLAGS (MAP_SHARED | MAP_FIXED)
-#else
-#define ADDR (void *)(0x0UL)
-#define FLAGS (MAP_SHARED)
-#endif
-
-static void check_bytes(char *addr)
-{
-       printf("First hex is %x\n", *((unsigned int *)addr));
-}
-
-static void write_bytes(char *addr)
-{
-       unsigned long i;
-
-       for (i = 0; i < LENGTH; i++)
-               *(addr + i) = (char)i;
-}
-
-static void read_bytes(char *addr)
-{
-       unsigned long i;
-
-       check_bytes(addr);
-       for (i = 0; i < LENGTH; i++)
-               if (*(addr + i) != (char)i) {
-                       printf("Mismatch at %lu\n", i);
-                       break;
-               }
-}
-
-int main(void)
-{
-       void *addr;
-       int fd;
-
-       fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
-       if (fd < 0) {
-               perror("Open failed");
-               exit(1);
-       }
-
-       addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
-       if (addr == MAP_FAILED) {
-               perror("mmap");
-               unlink(FILE_NAME);
-               exit(1);
-       }
-
-       printf("Returned address is %p\n", addr);
-       check_bytes(addr);
-       write_bytes(addr);
-       read_bytes(addr);
-
-       munmap(addr, LENGTH);
-       close(fd);
-       unlink(FILE_NAME);
-
-       return 0;
-}
diff --git a/Documentation/vm/hugepage-shm.c b/Documentation/vm/hugepage-shm.c
deleted file mode 100644 (file)
index 07956d8..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * hugepage-shm:
- *
- * Example of using huge page memory in a user application using Sys V shared
- * memory system calls.  In this example the app is requesting 256MB of
- * memory that is backed by huge pages.  The application uses the flag
- * SHM_HUGETLB in the shmget system call to inform the kernel that it is
- * requesting huge pages.
- *
- * For the ia64 architecture, the Linux kernel reserves Region number 4 for
- * huge pages.  That means that if one requires a fixed address, a huge page
- * aligned address starting with 0x800000... will be required.  If a fixed
- * address is not required, the kernel will select an address in the proper
- * range.
- * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
- *
- * Note: The default shared memory limit is quite low on many kernels,
- * you may need to increase it via:
- *
- * echo 268435456 > /proc/sys/kernel/shmmax
- *
- * This will increase the maximum size per shared memory segment to 256MB.
- * The other limit that you will hit eventually is shmall which is the
- * total amount of shared memory in pages. To set it to 16GB on a system
- * with a 4kB pagesize do:
- *
- * echo 4194304 > /proc/sys/kernel/shmall
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/mman.h>
-
-#ifndef SHM_HUGETLB
-#define SHM_HUGETLB 04000
-#endif
-
-#define LENGTH (256UL*1024*1024)
-
-#define dprintf(x)  printf(x)
-
-/* Only ia64 requires this */
-#ifdef __ia64__
-#define ADDR (void *)(0x8000000000000000UL)
-#define SHMAT_FLAGS (SHM_RND)
-#else
-#define ADDR (void *)(0x0UL)
-#define SHMAT_FLAGS (0)
-#endif
-
-int main(void)
-{
-       int shmid;
-       unsigned long i;
-       char *shmaddr;
-
-       if ((shmid = shmget(2, LENGTH,
-                           SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
-               perror("shmget");
-               exit(1);
-       }
-       printf("shmid: 0x%x\n", shmid);
-
-       shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
-       if (shmaddr == (char *)-1) {
-               perror("Shared memory attach failure");
-               shmctl(shmid, IPC_RMID, NULL);
-               exit(2);
-       }
-       printf("shmaddr: %p\n", shmaddr);
-
-       dprintf("Starting the writes:\n");
-       for (i = 0; i < LENGTH; i++) {
-               shmaddr[i] = (char)(i);
-               if (!(i % (1024 * 1024)))
-                       dprintf(".");
-       }
-       dprintf("\n");
-
-       dprintf("Starting the Check...");
-       for (i = 0; i < LENGTH; i++)
-               if (shmaddr[i] != (char)i)
-                       printf("\nIndex %lu mismatched\n", i);
-       dprintf("Done.\n");
-
-       if (shmdt((const void *)shmaddr) != 0) {
-               perror("Detach failure");
-               shmctl(shmid, IPC_RMID, NULL);
-               exit(3);
-       }
-
-       shmctl(shmid, IPC_RMID, NULL);
-
-       return 0;
-}
diff --git a/Documentation/vm/map_hugetlb.c b/Documentation/vm/map_hugetlb.c
deleted file mode 100644 (file)
index eda1a6d..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Example of using hugepage memory in a user application using the mmap
- * system call with MAP_HUGETLB flag.  Before running this program make
- * sure the administrator has allocated enough default sized huge pages
- * to cover the 256 MB allocation.
- *
- * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
- * That means the addresses starting with 0x800000... will need to be
- * specified.  Specifying a fixed address is not required on ppc64, i386
- * or x86_64.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-
-#define LENGTH (256UL*1024*1024)
-#define PROTECTION (PROT_READ | PROT_WRITE)
-
-#ifndef MAP_HUGETLB
-#define MAP_HUGETLB 0x40000 /* arch specific */
-#endif
-
-/* Only ia64 requires this */
-#ifdef __ia64__
-#define ADDR (void *)(0x8000000000000000UL)
-#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED)
-#else
-#define ADDR (void *)(0x0UL)
-#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
-#endif
-
-static void check_bytes(char *addr)
-{
-       printf("First hex is %x\n", *((unsigned int *)addr));
-}
-
-static void write_bytes(char *addr)
-{
-       unsigned long i;
-
-       for (i = 0; i < LENGTH; i++)
-               *(addr + i) = (char)i;
-}
-
-static void read_bytes(char *addr)
-{
-       unsigned long i;
-
-       check_bytes(addr);
-       for (i = 0; i < LENGTH; i++)
-               if (*(addr + i) != (char)i) {
-                       printf("Mismatch at %lu\n", i);
-                       break;
-               }
-}
-
-int main(void)
-{
-       void *addr;
-
-       addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
-       if (addr == MAP_FAILED) {
-               perror("mmap");
-               exit(1);
-       }
-
-       printf("Returned address is %p\n", addr);
-       check_bytes(addr);
-       write_bytes(addr);
-       read_bytes(addr);
-
-       munmap(addr, LENGTH);
-
-       return 0;
-}
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
deleted file mode 100644 (file)
index 0b13f02..0000000
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * page-types: Tool for querying page flags
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should find a copy of v2 of the GNU General Public License somewhere on
- * your Linux system; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2009 Intel corporation
- *
- * Authors: Wu Fengguang <fengguang.wu@intel.com>
- */
-
-#define _LARGEFILE64_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <getopt.h>
-#include <limits.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/fcntl.h>
-#include <sys/mount.h>
-#include <sys/statfs.h>
-#include "../../include/linux/magic.h"
-
-
-#ifndef MAX_PATH
-# define MAX_PATH 256
-#endif
-
-#ifndef STR
-# define _STR(x) #x
-# define STR(x) _STR(x)
-#endif
-
-/*
- * pagemap kernel ABI bits
- */
-
-#define PM_ENTRY_BYTES      sizeof(uint64_t)
-#define PM_STATUS_BITS      3
-#define PM_STATUS_OFFSET    (64 - PM_STATUS_BITS)
-#define PM_STATUS_MASK      (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET)
-#define PM_STATUS(nr)       (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK)
-#define PM_PSHIFT_BITS      6
-#define PM_PSHIFT_OFFSET    (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
-#define PM_PSHIFT_MASK      (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
-#define PM_PSHIFT(x)        (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
-#define PM_PFRAME_MASK      ((1LL << PM_PSHIFT_OFFSET) - 1)
-#define PM_PFRAME(x)        ((x) & PM_PFRAME_MASK)
-
-#define PM_PRESENT          PM_STATUS(4LL)
-#define PM_SWAP             PM_STATUS(2LL)
-
-
-/*
- * kernel page flags
- */
-
-#define KPF_BYTES              8
-#define PROC_KPAGEFLAGS                "/proc/kpageflags"
-
-/* copied from kpageflags_read() */
-#define KPF_LOCKED             0
-#define KPF_ERROR              1
-#define KPF_REFERENCED         2
-#define KPF_UPTODATE           3
-#define KPF_DIRTY              4
-#define KPF_LRU                        5
-#define KPF_ACTIVE             6
-#define KPF_SLAB               7
-#define KPF_WRITEBACK          8
-#define KPF_RECLAIM            9
-#define KPF_BUDDY              10
-
-/* [11-20] new additions in 2.6.31 */
-#define KPF_MMAP               11
-#define KPF_ANON               12
-#define KPF_SWAPCACHE          13
-#define KPF_SWAPBACKED         14
-#define KPF_COMPOUND_HEAD      15
-#define KPF_COMPOUND_TAIL      16
-#define KPF_HUGE               17
-#define KPF_UNEVICTABLE                18
-#define KPF_HWPOISON           19
-#define KPF_NOPAGE             20
-#define KPF_KSM                        21
-#define KPF_THP                        22
-
-/* [32-] kernel hacking assistances */
-#define KPF_RESERVED           32
-#define KPF_MLOCKED            33
-#define KPF_MAPPEDTODISK       34
-#define KPF_PRIVATE            35
-#define KPF_PRIVATE_2          36
-#define KPF_OWNER_PRIVATE      37
-#define KPF_ARCH               38
-#define KPF_UNCACHED           39
-
-/* [48-] take some arbitrary free slots for expanding overloaded flags
- * not part of kernel API
- */
-#define KPF_READAHEAD          48
-#define KPF_SLOB_FREE          49
-#define KPF_SLUB_FROZEN                50
-#define KPF_SLUB_DEBUG         51
-
-#define KPF_ALL_BITS           ((uint64_t)~0ULL)
-#define KPF_HACKERS_BITS       (0xffffULL << 32)
-#define KPF_OVERLOADED_BITS    (0xffffULL << 48)
-#define BIT(name)              (1ULL << KPF_##name)
-#define BITS_COMPOUND          (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL))
-
-static const char *page_flag_names[] = {
-       [KPF_LOCKED]            = "L:locked",
-       [KPF_ERROR]             = "E:error",
-       [KPF_REFERENCED]        = "R:referenced",
-       [KPF_UPTODATE]          = "U:uptodate",
-       [KPF_DIRTY]             = "D:dirty",
-       [KPF_LRU]               = "l:lru",
-       [KPF_ACTIVE]            = "A:active",
-       [KPF_SLAB]              = "S:slab",
-       [KPF_WRITEBACK]         = "W:writeback",
-       [KPF_RECLAIM]           = "I:reclaim",
-       [KPF_BUDDY]             = "B:buddy",
-
-       [KPF_MMAP]              = "M:mmap",
-       [KPF_ANON]              = "a:anonymous",
-       [KPF_SWAPCACHE]         = "s:swapcache",
-       [KPF_SWAPBACKED]        = "b:swapbacked",
-       [KPF_COMPOUND_HEAD]     = "H:compound_head",
-       [KPF_COMPOUND_TAIL]     = "T:compound_tail",
-       [KPF_HUGE]              = "G:huge",
-       [KPF_UNEVICTABLE]       = "u:unevictable",
-       [KPF_HWPOISON]          = "X:hwpoison",
-       [KPF_NOPAGE]            = "n:nopage",
-       [KPF_KSM]               = "x:ksm",
-       [KPF_THP]               = "t:thp",
-
-       [KPF_RESERVED]          = "r:reserved",
-       [KPF_MLOCKED]           = "m:mlocked",
-       [KPF_MAPPEDTODISK]      = "d:mappedtodisk",
-       [KPF_PRIVATE]           = "P:private",
-       [KPF_PRIVATE_2]         = "p:private_2",
-       [KPF_OWNER_PRIVATE]     = "O:owner_private",
-       [KPF_ARCH]              = "h:arch",
-       [KPF_UNCACHED]          = "c:uncached",
-
-       [KPF_READAHEAD]         = "I:readahead",
-       [KPF_SLOB_FREE]         = "P:slob_free",
-       [KPF_SLUB_FROZEN]       = "A:slub_frozen",
-       [KPF_SLUB_DEBUG]        = "E:slub_debug",
-};
-
-
-static const char *debugfs_known_mountpoints[] = {
-       "/sys/kernel/debug",
-       "/debug",
-       0,
-};
-
-/*
- * data structures
- */
-
-static int             opt_raw;        /* for kernel developers */
-static int             opt_list;       /* list pages (in ranges) */
-static int             opt_no_summary; /* don't show summary */
-static pid_t           opt_pid;        /* process to walk */
-
-#define MAX_ADDR_RANGES        1024
-static int             nr_addr_ranges;
-static unsigned long   opt_offset[MAX_ADDR_RANGES];
-static unsigned long   opt_size[MAX_ADDR_RANGES];
-
-#define MAX_VMAS       10240
-static int             nr_vmas;
-static unsigned long   pg_start[MAX_VMAS];
-static unsigned long   pg_end[MAX_VMAS];
-
-#define MAX_BIT_FILTERS        64
-static int             nr_bit_filters;
-static uint64_t                opt_mask[MAX_BIT_FILTERS];
-static uint64_t                opt_bits[MAX_BIT_FILTERS];
-
-static int             page_size;
-
-static int             pagemap_fd;
-static int             kpageflags_fd;
-
-static int             opt_hwpoison;
-static int             opt_unpoison;
-
-static char            hwpoison_debug_fs[MAX_PATH+1];
-static int             hwpoison_inject_fd;
-static int             hwpoison_forget_fd;
-
-#define HASH_SHIFT     13
-#define HASH_SIZE      (1 << HASH_SHIFT)
-#define HASH_MASK      (HASH_SIZE - 1)
-#define HASH_KEY(flags)        (flags & HASH_MASK)
-
-static unsigned long   total_pages;
-static unsigned long   nr_pages[HASH_SIZE];
-static uint64_t        page_flags[HASH_SIZE];
-
-
-/*
- * helper functions
- */
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#define min_t(type, x, y) ({                   \
-       type __min1 = (x);                      \
-       type __min2 = (y);                      \
-       __min1 < __min2 ? __min1 : __min2; })
-
-#define max_t(type, x, y) ({                   \
-       type __max1 = (x);                      \
-       type __max2 = (y);                      \
-       __max1 > __max2 ? __max1 : __max2; })
-
-static unsigned long pages2mb(unsigned long pages)
-{
-       return (pages * page_size) >> 20;
-}
-
-static void fatal(const char *x, ...)
-{
-       va_list ap;
-
-       va_start(ap, x);
-       vfprintf(stderr, x, ap);
-       va_end(ap);
-       exit(EXIT_FAILURE);
-}
-
-static int checked_open(const char *pathname, int flags)
-{
-       int fd = open(pathname, flags);
-
-       if (fd < 0) {
-               perror(pathname);
-               exit(EXIT_FAILURE);
-       }
-
-       return fd;
-}
-
-/*
- * pagemap/kpageflags routines
- */
-
-static unsigned long do_u64_read(int fd, char *name,
-                                uint64_t *buf,
-                                unsigned long index,
-                                unsigned long count)
-{
-       long bytes;
-
-       if (index > ULONG_MAX / 8)
-               fatal("index overflow: %lu\n", index);
-
-       if (lseek(fd, index * 8, SEEK_SET) < 0) {
-               perror(name);
-               exit(EXIT_FAILURE);
-       }
-
-       bytes = read(fd, buf, count * 8);
-       if (bytes < 0) {
-               perror(name);
-               exit(EXIT_FAILURE);
-       }
-       if (bytes % 8)
-               fatal("partial read: %lu bytes\n", bytes);
-
-       return bytes / 8;
-}
-
-static unsigned long kpageflags_read(uint64_t *buf,
-                                    unsigned long index,
-                                    unsigned long pages)
-{
-       return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages);
-}
-
-static unsigned long pagemap_read(uint64_t *buf,
-                                 unsigned long index,
-                                 unsigned long pages)
-{
-       return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages);
-}
-
-static unsigned long pagemap_pfn(uint64_t val)
-{
-       unsigned long pfn;
-
-       if (val & PM_PRESENT)
-               pfn = PM_PFRAME(val);
-       else
-               pfn = 0;
-
-       return pfn;
-}
-
-
-/*
- * page flag names
- */
-
-static char *page_flag_name(uint64_t flags)
-{
-       static char buf[65];
-       int present;
-       int i, j;
-
-       for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
-               present = (flags >> i) & 1;
-               if (!page_flag_names[i]) {
-                       if (present)
-                               fatal("unknown flag bit %d\n", i);
-                       continue;
-               }
-               buf[j++] = present ? page_flag_names[i][0] : '_';
-       }
-
-       return buf;
-}
-
-static char *page_flag_longname(uint64_t flags)
-{
-       static char buf[1024];
-       int i, n;
-
-       for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) {
-               if (!page_flag_names[i])
-                       continue;
-               if ((flags >> i) & 1)
-                       n += snprintf(buf + n, sizeof(buf) - n, "%s,",
-                                       page_flag_names[i] + 2);
-       }
-       if (n)
-               n--;
-       buf[n] = '\0';
-
-       return buf;
-}
-
-
-/*
- * page list and summary
- */
-
-static void show_page_range(unsigned long voffset,
-                           unsigned long offset, uint64_t flags)
-{
-       static uint64_t      flags0;
-       static unsigned long voff;
-       static unsigned long index;
-       static unsigned long count;
-
-       if (flags == flags0 && offset == index + count &&
-           (!opt_pid || voffset == voff + count)) {
-               count++;
-               return;
-       }
-
-       if (count) {
-               if (opt_pid)
-                       printf("%lx\t", voff);
-               printf("%lx\t%lx\t%s\n",
-                               index, count, page_flag_name(flags0));
-       }
-
-       flags0 = flags;
-       index  = offset;
-       voff   = voffset;
-       count  = 1;
-}
-
-static void show_page(unsigned long voffset,
-                     unsigned long offset, uint64_t flags)
-{
-       if (opt_pid)
-               printf("%lx\t", voffset);
-       printf("%lx\t%s\n", offset, page_flag_name(flags));
-}
-
-static void show_summary(void)
-{
-       int i;
-
-       printf("             flags\tpage-count       MB"
-               "  symbolic-flags\t\t\tlong-symbolic-flags\n");
-
-       for (i = 0; i < ARRAY_SIZE(nr_pages); i++) {
-               if (nr_pages[i])
-                       printf("0x%016llx\t%10lu %8lu  %s\t%s\n",
-                               (unsigned long long)page_flags[i],
-                               nr_pages[i],
-                               pages2mb(nr_pages[i]),
-                               page_flag_name(page_flags[i]),
-                               page_flag_longname(page_flags[i]));
-       }
-
-       printf("             total\t%10lu %8lu\n",
-                       total_pages, pages2mb(total_pages));
-}
-
-
-/*
- * page flag filters
- */
-
-static int bit_mask_ok(uint64_t flags)
-{
-       int i;
-
-       for (i = 0; i < nr_bit_filters; i++) {
-               if (opt_bits[i] == KPF_ALL_BITS) {
-                       if ((flags & opt_mask[i]) == 0)
-                               return 0;
-               } else {
-                       if ((flags & opt_mask[i]) != opt_bits[i])
-                               return 0;
-               }
-       }
-
-       return 1;
-}
-
-static uint64_t expand_overloaded_flags(uint64_t flags)
-{
-       /* SLOB/SLUB overload several page flags */
-       if (flags & BIT(SLAB)) {
-               if (flags & BIT(PRIVATE))
-                       flags ^= BIT(PRIVATE) | BIT(SLOB_FREE);
-               if (flags & BIT(ACTIVE))
-                       flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN);
-               if (flags & BIT(ERROR))
-                       flags ^= BIT(ERROR) | BIT(SLUB_DEBUG);
-       }
-
-       /* PG_reclaim is overloaded as PG_readahead in the read path */
-       if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM))
-               flags ^= BIT(RECLAIM) | BIT(READAHEAD);
-
-       return flags;
-}
-
-static uint64_t well_known_flags(uint64_t flags)
-{
-       /* hide flags intended only for kernel hacker */
-       flags &= ~KPF_HACKERS_BITS;
-
-       /* hide non-hugeTLB compound pages */
-       if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE)))
-               flags &= ~BITS_COMPOUND;
-
-       return flags;
-}
-
-static uint64_t kpageflags_flags(uint64_t flags)
-{
-       flags = expand_overloaded_flags(flags);
-
-       if (!opt_raw)
-               flags = well_known_flags(flags);
-
-       return flags;
-}
-
-/* verify that a mountpoint is actually a debugfs instance */
-static int debugfs_valid_mountpoint(const char *debugfs)
-{
-       struct statfs st_fs;
-
-       if (statfs(debugfs, &st_fs) < 0)
-               return -ENOENT;
-       else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
-               return -ENOENT;
-
-       return 0;
-}
-
-/* find the path to the mounted debugfs */
-static const char *debugfs_find_mountpoint(void)
-{
-       const char **ptr;
-       char type[100];
-       FILE *fp;
-
-       ptr = debugfs_known_mountpoints;
-       while (*ptr) {
-               if (debugfs_valid_mountpoint(*ptr) == 0) {
-                       strcpy(hwpoison_debug_fs, *ptr);
-                       return hwpoison_debug_fs;
-               }
-               ptr++;
-       }
-
-       /* give up and parse /proc/mounts */
-       fp = fopen("/proc/mounts", "r");
-       if (fp == NULL)
-               perror("Can't open /proc/mounts for read");
-
-       while (fscanf(fp, "%*s %"
-                     STR(MAX_PATH)
-                     "s %99s %*s %*d %*d\n",
-                     hwpoison_debug_fs, type) == 2) {
-               if (strcmp(type, "debugfs") == 0)
-                       break;
-       }
-       fclose(fp);
-
-       if (strcmp(type, "debugfs") != 0)
-               return NULL;
-
-       return hwpoison_debug_fs;
-}
-
-/* mount the debugfs somewhere if it's not mounted */
-
-static void debugfs_mount(void)
-{
-       const char **ptr;
-
-       /* see if it's already mounted */
-       if (debugfs_find_mountpoint())
-               return;
-
-       ptr = debugfs_known_mountpoints;
-       while (*ptr) {
-               if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) {
-                       /* save the mountpoint */
-                       strcpy(hwpoison_debug_fs, *ptr);
-                       break;
-               }
-               ptr++;
-       }
-
-       if (*ptr == NULL) {
-               perror("mount debugfs");
-               exit(EXIT_FAILURE);
-       }
-}
-
-/*
- * page actions
- */
-
-static void prepare_hwpoison_fd(void)
-{
-       char buf[MAX_PATH + 1];
-
-       debugfs_mount();
-
-       if (opt_hwpoison && !hwpoison_inject_fd) {
-               snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn",
-                       hwpoison_debug_fs);
-               hwpoison_inject_fd = checked_open(buf, O_WRONLY);
-       }
-
-       if (opt_unpoison && !hwpoison_forget_fd) {
-               snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn",
-                       hwpoison_debug_fs);
-               hwpoison_forget_fd = checked_open(buf, O_WRONLY);
-       }
-}
-
-static int hwpoison_page(unsigned long offset)
-{
-       char buf[100];
-       int len;
-
-       len = sprintf(buf, "0x%lx\n", offset);
-       len = write(hwpoison_inject_fd, buf, len);
-       if (len < 0) {
-               perror("hwpoison inject");
-               return len;
-       }
-       return 0;
-}
-
-static int unpoison_page(unsigned long offset)
-{
-       char buf[100];
-       int len;
-
-       len = sprintf(buf, "0x%lx\n", offset);
-       len = write(hwpoison_forget_fd, buf, len);
-       if (len < 0) {
-               perror("hwpoison forget");
-               return len;
-       }
-       return 0;
-}
-
-/*
- * page frame walker
- */
-
-static int hash_slot(uint64_t flags)
-{
-       int k = HASH_KEY(flags);
-       int i;
-
-       /* Explicitly reserve slot 0 for flags 0: the following logic
-        * cannot distinguish an unoccupied slot from slot (flags==0).
-        */
-       if (flags == 0)
-               return 0;
-
-       /* search through the remaining (HASH_SIZE-1) slots */
-       for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) {
-               if (!k || k >= ARRAY_SIZE(page_flags))
-                       k = 1;
-               if (page_flags[k] == 0) {
-                       page_flags[k] = flags;
-                       return k;
-               }
-               if (page_flags[k] == flags)
-                       return k;
-       }
-
-       fatal("hash table full: bump up HASH_SHIFT?\n");
-       exit(EXIT_FAILURE);
-}
-
-static void add_page(unsigned long voffset,
-                    unsigned long offset, uint64_t flags)
-{
-       flags = kpageflags_flags(flags);
-
-       if (!bit_mask_ok(flags))
-               return;
-
-       if (opt_hwpoison)
-               hwpoison_page(offset);
-       if (opt_unpoison)
-               unpoison_page(offset);
-
-       if (opt_list == 1)
-               show_page_range(voffset, offset, flags);
-       else if (opt_list == 2)
-               show_page(voffset, offset, flags);
-
-       nr_pages[hash_slot(flags)]++;
-       total_pages++;
-}
-
-#define KPAGEFLAGS_BATCH       (64 << 10)      /* 64k pages */
-static void walk_pfn(unsigned long voffset,
-                    unsigned long index,
-                    unsigned long count)
-{
-       uint64_t buf[KPAGEFLAGS_BATCH];
-       unsigned long batch;
-       long pages;
-       unsigned long i;
-
-       while (count) {
-               batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH);
-               pages = kpageflags_read(buf, index, batch);
-               if (pages == 0)
-                       break;
-
-               for (i = 0; i < pages; i++)
-                       add_page(voffset + i, index + i, buf[i]);
-
-               index += pages;
-               count -= pages;
-       }
-}
-
-#define PAGEMAP_BATCH  (64 << 10)
-static void walk_vma(unsigned long index, unsigned long count)
-{
-       uint64_t buf[PAGEMAP_BATCH];
-       unsigned long batch;
-       unsigned long pages;
-       unsigned long pfn;
-       unsigned long i;
-
-       while (count) {
-               batch = min_t(unsigned long, count, PAGEMAP_BATCH);
-               pages = pagemap_read(buf, index, batch);
-               if (pages == 0)
-                       break;
-
-               for (i = 0; i < pages; i++) {
-                       pfn = pagemap_pfn(buf[i]);
-                       if (pfn)
-                               walk_pfn(index + i, pfn, 1);
-               }
-
-               index += pages;
-               count -= pages;
-       }
-}
-
-static void walk_task(unsigned long index, unsigned long count)
-{
-       const unsigned long end = index + count;
-       unsigned long start;
-       int i = 0;
-
-       while (index < end) {
-
-               while (pg_end[i] <= index)
-                       if (++i >= nr_vmas)
-                               return;
-               if (pg_start[i] >= end)
-                       return;
-
-               start = max_t(unsigned long, pg_start[i], index);
-               index = min_t(unsigned long, pg_end[i], end);
-
-               assert(start < index);
-               walk_vma(start, index - start);
-       }
-}
-
-static void add_addr_range(unsigned long offset, unsigned long size)
-{
-       if (nr_addr_ranges >= MAX_ADDR_RANGES)
-               fatal("too many addr ranges\n");
-
-       opt_offset[nr_addr_ranges] = offset;
-       opt_size[nr_addr_ranges] = min_t(unsigned long, size, ULONG_MAX-offset);
-       nr_addr_ranges++;
-}
-
-static void walk_addr_ranges(void)
-{
-       int i;
-
-       kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY);
-
-       if (!nr_addr_ranges)
-               add_addr_range(0, ULONG_MAX);
-
-       for (i = 0; i < nr_addr_ranges; i++)
-               if (!opt_pid)
-                       walk_pfn(0, opt_offset[i], opt_size[i]);
-               else
-                       walk_task(opt_offset[i], opt_size[i]);
-
-       close(kpageflags_fd);
-}
-
-
-/*
- * user interface
- */
-
-static const char *page_flag_type(uint64_t flag)
-{
-       if (flag & KPF_HACKERS_BITS)
-               return "(r)";
-       if (flag & KPF_OVERLOADED_BITS)
-               return "(o)";
-       return "   ";
-}
-
-static void usage(void)
-{
-       int i, j;
-
-       printf(
-"page-types [options]\n"
-"            -r|--raw                   Raw mode, for kernel developers\n"
-"            -d|--describe flags        Describe flags\n"
-"            -a|--addr    addr-spec     Walk a range of pages\n"
-"            -b|--bits    bits-spec     Walk pages with specified bits\n"
-"            -p|--pid     pid           Walk process address space\n"
-#if 0 /* planned features */
-"            -f|--file    filename      Walk file address space\n"
-#endif
-"            -l|--list                  Show page details in ranges\n"
-"            -L|--list-each             Show page details one by one\n"
-"            -N|--no-summary            Don't show summary info\n"
-"            -X|--hwpoison              hwpoison pages\n"
-"            -x|--unpoison              unpoison pages\n"
-"            -h|--help                  Show this usage message\n"
-"flags:\n"
-"            0x10                       bitfield format, e.g.\n"
-"            anon                       bit-name, e.g.\n"
-"            0x10,anon                  comma-separated list, e.g.\n"
-"addr-spec:\n"
-"            N                          one page at offset N (unit: pages)\n"
-"            N+M                        pages range from N to N+M-1\n"
-"            N,M                        pages range from N to M-1\n"
-"            N,                         pages range from N to end\n"
-"            ,M                         pages range from 0 to M-1\n"
-"bits-spec:\n"
-"            bit1,bit2                  (flags & (bit1|bit2)) != 0\n"
-"            bit1,bit2=bit1             (flags & (bit1|bit2)) == bit1\n"
-"            bit1,~bit2                 (flags & (bit1|bit2)) == bit1\n"
-"            =bit1,bit2                 flags == (bit1|bit2)\n"
-"bit-names:\n"
-       );
-
-       for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
-               if (!page_flag_names[i])
-                       continue;
-               printf("%16s%s", page_flag_names[i] + 2,
-                                page_flag_type(1ULL << i));
-               if (++j > 3) {
-                       j = 0;
-                       putchar('\n');
-               }
-       }
-       printf("\n                                   "
-               "(r) raw mode bits  (o) overloaded bits\n");
-}
-
-static unsigned long long parse_number(const char *str)
-{
-       unsigned long long n;
-
-       n = strtoll(str, NULL, 0);
-
-       if (n == 0 && str[0] != '0')
-               fatal("invalid name or number: %s\n", str);
-
-       return n;
-}
-
-static void parse_pid(const char *str)
-{
-       FILE *file;
-       char buf[5000];
-
-       opt_pid = parse_number(str);
-
-       sprintf(buf, "/proc/%d/pagemap", opt_pid);
-       pagemap_fd = checked_open(buf, O_RDONLY);
-
-       sprintf(buf, "/proc/%d/maps", opt_pid);
-       file = fopen(buf, "r");
-       if (!file) {
-               perror(buf);
-               exit(EXIT_FAILURE);
-       }
-
-       while (fgets(buf, sizeof(buf), file) != NULL) {
-               unsigned long vm_start;
-               unsigned long vm_end;
-               unsigned long long pgoff;
-               int major, minor;
-               char r, w, x, s;
-               unsigned long ino;
-               int n;
-
-               n = sscanf(buf, "%lx-%lx %c%c%c%c %llx %x:%x %lu",
-                          &vm_start,
-                          &vm_end,
-                          &r, &w, &x, &s,
-                          &pgoff,
-                          &major, &minor,
-                          &ino);
-               if (n < 10) {
-                       fprintf(stderr, "unexpected line: %s\n", buf);
-                       continue;
-               }
-               pg_start[nr_vmas] = vm_start / page_size;
-               pg_end[nr_vmas] = vm_end / page_size;
-               if (++nr_vmas >= MAX_VMAS) {
-                       fprintf(stderr, "too many VMAs\n");
-                       break;
-               }
-       }
-       fclose(file);
-}
-
-static void parse_file(const char *name)
-{
-}
-
-static void parse_addr_range(const char *optarg)
-{
-       unsigned long offset;
-       unsigned long size;
-       char *p;
-
-       p = strchr(optarg, ',');
-       if (!p)
-               p = strchr(optarg, '+');
-
-       if (p == optarg) {
-               offset = 0;
-               size   = parse_number(p + 1);
-       } else if (p) {
-               offset = parse_number(optarg);
-               if (p[1] == '\0')
-                       size = ULONG_MAX;
-               else {
-                       size = parse_number(p + 1);
-                       if (*p == ',') {
-                               if (size < offset)
-                                       fatal("invalid range: %lu,%lu\n",
-                                                       offset, size);
-                               size -= offset;
-                       }
-               }
-       } else {
-               offset = parse_number(optarg);
-               size   = 1;
-       }
-
-       add_addr_range(offset, size);
-}
-
-static void add_bits_filter(uint64_t mask, uint64_t bits)
-{
-       if (nr_bit_filters >= MAX_BIT_FILTERS)
-               fatal("too much bit filters\n");
-
-       opt_mask[nr_bit_filters] = mask;
-       opt_bits[nr_bit_filters] = bits;
-       nr_bit_filters++;
-}
-
-static uint64_t parse_flag_name(const char *str, int len)
-{
-       int i;
-
-       if (!*str || !len)
-               return 0;
-
-       if (len <= 8 && !strncmp(str, "compound", len))
-               return BITS_COMPOUND;
-
-       for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
-               if (!page_flag_names[i])
-                       continue;
-               if (!strncmp(str, page_flag_names[i] + 2, len))
-                       return 1ULL << i;
-       }
-
-       return parse_number(str);
-}
-
-static uint64_t parse_flag_names(const char *str, int all)
-{
-       const char *p    = str;
-       uint64_t   flags = 0;
-
-       while (1) {
-               if (*p == ',' || *p == '=' || *p == '\0') {
-                       if ((*str != '~') || (*str == '~' && all && *++str))
-                               flags |= parse_flag_name(str, p - str);
-                       if (*p != ',')
-                               break;
-                       str = p + 1;
-               }
-               p++;
-       }
-
-       return flags;
-}
-
-static void parse_bits_mask(const char *optarg)
-{
-       uint64_t mask;
-       uint64_t bits;
-       const char *p;
-
-       p = strchr(optarg, '=');
-       if (p == optarg) {
-               mask = KPF_ALL_BITS;
-               bits = parse_flag_names(p + 1, 0);
-       } else if (p) {
-               mask = parse_flag_names(optarg, 0);
-               bits = parse_flag_names(p + 1, 0);
-       } else if (strchr(optarg, '~')) {
-               mask = parse_flag_names(optarg, 1);
-               bits = parse_flag_names(optarg, 0);
-       } else {
-               mask = parse_flag_names(optarg, 0);
-               bits = KPF_ALL_BITS;
-       }
-
-       add_bits_filter(mask, bits);
-}
-
-static void describe_flags(const char *optarg)
-{
-       uint64_t flags = parse_flag_names(optarg, 0);
-
-       printf("0x%016llx\t%s\t%s\n",
-               (unsigned long long)flags,
-               page_flag_name(flags),
-               page_flag_longname(flags));
-}
-
-static const struct option opts[] = {
-       { "raw"       , 0, NULL, 'r' },
-       { "pid"       , 1, NULL, 'p' },
-       { "file"      , 1, NULL, 'f' },
-       { "addr"      , 1, NULL, 'a' },
-       { "bits"      , 1, NULL, 'b' },
-       { "describe"  , 1, NULL, 'd' },
-       { "list"      , 0, NULL, 'l' },
-       { "list-each" , 0, NULL, 'L' },
-       { "no-summary", 0, NULL, 'N' },
-       { "hwpoison"  , 0, NULL, 'X' },
-       { "unpoison"  , 0, NULL, 'x' },
-       { "help"      , 0, NULL, 'h' },
-       { NULL        , 0, NULL, 0 }
-};
-
-int main(int argc, char *argv[])
-{
-       int c;
-
-       page_size = getpagesize();
-
-       while ((c = getopt_long(argc, argv,
-                               "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) {
-               switch (c) {
-               case 'r':
-                       opt_raw = 1;
-                       break;
-               case 'p':
-                       parse_pid(optarg);
-                       break;
-               case 'f':
-                       parse_file(optarg);
-                       break;
-               case 'a':
-                       parse_addr_range(optarg);
-                       break;
-               case 'b':
-                       parse_bits_mask(optarg);
-                       break;
-               case 'd':
-                       describe_flags(optarg);
-                       exit(0);
-               case 'l':
-                       opt_list = 1;
-                       break;
-               case 'L':
-                       opt_list = 2;
-                       break;
-               case 'N':
-                       opt_no_summary = 1;
-                       break;
-               case 'X':
-                       opt_hwpoison = 1;
-                       prepare_hwpoison_fd();
-                       break;
-               case 'x':
-                       opt_unpoison = 1;
-                       prepare_hwpoison_fd();
-                       break;
-               case 'h':
-                       usage();
-                       exit(0);
-               default:
-                       usage();
-                       exit(1);
-               }
-       }
-
-       if (opt_list && opt_pid)
-               printf("voffset\t");
-       if (opt_list == 1)
-               printf("offset\tlen\tflags\n");
-       if (opt_list == 2)
-               printf("offset\tflags\n");
-
-       walk_addr_ranges();
-
-       if (opt_list == 1)
-               show_page_range(0, 0, 0);  /* drain the buffer */
-
-       if (opt_no_summary)
-               return 0;
-
-       if (opt_list)
-               printf("\n\n");
-
-       show_summary();
-
-       return 0;
-}
diff --git a/Documentation/watchdog/00-INDEX b/Documentation/watchdog/00-INDEX
deleted file mode 100644 (file)
index fc9082a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-00-INDEX
-       - this file.
-convert_drivers_to_kernel_api.txt
-       - how-to for converting old watchdog drivers to the new kernel API.
-hpwdt.txt
-       - information on the HP iLO2 NMI watchdog
-pcwd-watchdog.txt
-       - documentation for Berkshire Products PC Watchdog ISA cards.
-src/
-       - directory holding watchdog related example programs.
-watchdog-api.txt
-       - description of the Linux Watchdog driver API.
-watchdog-kernel-api.txt
-       - description of the Linux WatchDog Timer Driver Core kernel API.
-watchdog-parameters.txt
-       - information on driver parameters (for drivers other than
-         the ones that have driver-specific files here)
-wdt.txt
-       - description of the Watchdog Timer Interfaces for Linux.
index be8119bb15d209f98012c24159d0ff2b78c0eebf..271b8850dde76af34470123fd95cdbc0fca21111 100644 (file)
@@ -59,6 +59,10 @@ Here is a overview of the functions and probably needed actions:
        WDIOC_GETTIMEOUT:
                No preparations needed
 
+       WDIOC_GETTIMELEFT:
+               It needs get_timeleft() callback to be defined. Otherwise it
+               will return EOPNOTSUPP
+
   Other IOCTLs can be served using the ioctl-callback. Note that this is mainly
   intended for porting old drivers; new drivers should not invent private IOCTLs.
   Private IOCTLs are processed first. When the callback returns with
index 9e162465b0cf024844a507b78c640ac759e7a0b1..227f6cd0e5face25f9e02f83e599f54cb808ddaa 100644 (file)
@@ -1,6 +1,6 @@
 The Linux WatchDog Timer Driver Core kernel API.
 ===============================================
-Last reviewed: 29-Nov-2011
+Last reviewed: 16-Mar-2012
 
 Wim Van Sebroeck <wim@iguana.be>
 
@@ -77,6 +77,7 @@ struct watchdog_ops {
        int (*ping)(struct watchdog_device *);
        unsigned int (*status)(struct watchdog_device *);
        int (*set_timeout)(struct watchdog_device *, unsigned int);
+       unsigned int (*get_timeleft)(struct watchdog_device *);
        long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
 };
 
@@ -117,11 +118,13 @@ they are supported. These optional routines/operations are:
   status of the device is reported with watchdog WDIOF_* status flags/bits.
 * set_timeout: this routine checks and changes the timeout of the watchdog
   timer device. It returns 0 on success, -EINVAL for "parameter out of range"
-  and -EIO for "could not write value to the watchdog". On success the timeout
-  value of the watchdog_device will be changed to the value that was just used
-  to re-program the watchdog timer device.
+  and -EIO for "could not write value to the watchdog". On success this
+  routine should set the timeout value of the watchdog_device to the
+  achieved timeout value (which may be different from the requested one
+  because the watchdog does not necessarily has a 1 second resolution).
   (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
   watchdog's info structure).
+* get_timeleft: this routines returns the time that's left before a reset.
 * ioctl: if this routine is present then it will be called first before we do
   our own internal ioctl call handling. This routine should return -ENOIOCTLCMD
   if a command is not supported. The parameters that are passed to the ioctl
index 3d11fa581bb7d14d0b58a033a0079e4806fbf3c9..64168f6dd89ee0d8b6de21f53f64d6b30bc08f38 100644 (file)
@@ -2225,13 +2225,16 @@ W:      http://lanana.org/docs/device-list/index.html
 S:     Maintained
 
 DEVICE-MAPPER  (LVM)
-P:     Alasdair Kergon
+M:     Alasdair Kergon <agk@redhat.com>
+M:     dm-devel@redhat.com
 L:     dm-devel@redhat.com
 W:     http://sources.redhat.com/dm
 Q:     http://patchwork.kernel.org/project/dm-devel/list/
+T:     quilt http://people.redhat.com/agk/patches/linux/editing/
 S:     Maintained
 F:     Documentation/device-mapper/
 F:     drivers/md/dm*
+F:     drivers/md/persistent-data/
 F:     include/linux/device-mapper.h
 F:     include/linux/dm-*.h
 
@@ -5182,7 +5185,7 @@ F:        kernel/delayacct.c
 PERFORMANCE EVENTS SUBSYSTEM
 M:     Peter Zijlstra <a.p.zijlstra@chello.nl>
 M:     Paul Mackerras <paulus@samba.org>
-M:     Ingo Molnar <mingo@elte.hu>
+M:     Ingo Molnar <mingo@redhat.com>
 M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
 S:     Supported
@@ -5773,6 +5776,12 @@ F:       drivers/media/common/saa7146*
 F:     drivers/media/video/*7146*
 F:     include/media/*7146*
 
+SAMSUNG LAPTOP DRIVER
+M:     Corentin Chary <corentincj@iksaif.net>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/samsung-laptop.c
+
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Sangbeom Kim <sbkim73@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -5824,7 +5833,7 @@ S:        Maintained
 F:     drivers/watchdog/sc1200wdt.c
 
 SCHEDULER
-M:     Ingo Molnar <mingo@elte.hu>
+M:     Ingo Molnar <mingo@redhat.com>
 M:     Peter Zijlstra <peterz@infradead.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core
 S:     Maintained
index a6f14f622d1388bee0a6663679762f155991dadc..684eb5af439dc5cee005f51675c2db814a29bf38 100644 (file)
@@ -213,4 +213,7 @@ config HAVE_CMPXCHG_LOCAL
 config HAVE_CMPXCHG_DOUBLE
        bool
 
+config ARCH_WANT_OLD_COMPAT_IPC
+       bool
+
 source "kernel/gcov/Kconfig"
index be61670d40963c78fa52e9d2cfef36b15abafe8f..2a542a506557dc83e2643a2480031eb291dd2ab9 100644 (file)
@@ -13,7 +13,6 @@
 #include <generated/utsrelease.h>
 #include <linux/mm.h>
 
-#include <asm/system.h>
 #include <asm/console.h>
 #include <asm/hwrpb.h>
 #include <asm/pgtable.h>
index c98865f21423016cd8220a574da6d69ca5cc42c4..d6ad191698dad32858f7e94cda5b1bf68f660065 100644 (file)
@@ -15,7 +15,6 @@
 #include <generated/utsrelease.h>
 #include <linux/mm.h>
 
-#include <asm/system.h>
 #include <asm/console.h>
 #include <asm/hwrpb.h>
 #include <asm/pgtable.h>
index f3d98089b3dc36c891e31327a93460121fa41c53..b06812bcac83b911cf43613cba8f1d6619fd380d 100644 (file)
@@ -4,7 +4,6 @@
  * initial bootloader stuff..
  */
 
-#include <asm/system.h>
 
        .set noreorder
        .globl  __start
index ded57d9a80e1adee23896c9a296476e383bcc2c5..3baf2d1e908df5760f1304bab309ae70877eee03 100644 (file)
@@ -11,7 +11,6 @@
 #include <generated/utsrelease.h>
 #include <linux/mm.h>
 
-#include <asm/system.h>
 #include <asm/console.h>
 #include <asm/hwrpb.h>
 #include <asm/pgtable.h>
index 640f909ddd41a68ea1bf90c5cba66c6287187d5b..f62251e82ffac39579e26c0ee6f77f58c1bd9ac5 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 #include <asm/barrier.h>
-#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -169,6 +168,73 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
        return result;
 }
 
+/*
+ * Atomic exchange routines.
+ */
+
+#define __ASM__MB
+#define ____xchg(type, args...)                __xchg ## type ## _local(args)
+#define ____cmpxchg(type, args...)     __cmpxchg ## type ## _local(args)
+#include <asm/xchg.h>
+
+#define xchg_local(ptr,x)                                              \
+  ({                                                                   \
+     __typeof__(*(ptr)) _x_ = (x);                                     \
+     (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,      \
+                                      sizeof(*(ptr)));                 \
+  })
+
+#define cmpxchg_local(ptr, o, n)                                       \
+  ({                                                                   \
+     __typeof__(*(ptr)) _o_ = (o);                                     \
+     __typeof__(*(ptr)) _n_ = (n);                                     \
+     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,   \
+                                         (unsigned long)_n_,           \
+                                         sizeof(*(ptr)));              \
+  })
+
+#define cmpxchg64_local(ptr, o, n)                                     \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+  })
+
+#ifdef CONFIG_SMP
+#undef __ASM__MB
+#define __ASM__MB      "\tmb\n"
+#endif
+#undef ____xchg
+#undef ____cmpxchg
+#define ____xchg(type, args...)                __xchg ##type(args)
+#define ____cmpxchg(type, args...)     __cmpxchg ##type(args)
+#include <asm/xchg.h>
+
+#define xchg(ptr,x)                                                    \
+  ({                                                                   \
+     __typeof__(*(ptr)) _x_ = (x);                                     \
+     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_,            \
+                                sizeof(*(ptr)));                       \
+  })
+
+#define cmpxchg(ptr, o, n)                                             \
+  ({                                                                   \
+     __typeof__(*(ptr)) _o_ = (o);                                     \
+     __typeof__(*(ptr)) _n_ = (n);                                     \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,         \
+                                   (unsigned long)_n_, sizeof(*(ptr)));\
+  })
+
+#define cmpxchg64(ptr, o, n)                                           \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg((ptr), (o), (n));                                       \
+  })
+
+#undef __ASM__MB
+#undef ____cmpxchg
+
+#define __HAVE_ARCH_CMPXCHG 1
+
 #define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
index e96fe880e310fc91e0f8b74ab5e6a96a8b84388e..a3a579dfdb4d2d283d8c54b7bd33a3467ffa4936 100644 (file)
@@ -21,4 +21,6 @@
 #define AT_L2_CACHESHAPE       36
 #define AT_L3_CACHESHAPE       37
 
+#define AT_VECTOR_SIZE_ARCH 4 /* entries in ARCH_DLINFO */
+
 #endif /* __ASM_ALPHA_AUXVEC_H */
index f7cb4b4609549df960fd6f87229bb5550d22403d..8ee6c516279cbd8943982875416000968d9029dc 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ALPHA_LCA__H__
 #define __ALPHA_LCA__H__
 
-#include <asm/system.h>
 #include <asm/compiler.h>
+#include <asm/mce.h>
 
 /*
  * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068,
index 9f67a056b46181e36753575698ea40d6944e6fd2..ad44bef29fbaaeafd0b5799d9bc9c2f00e75722b 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/types.h>
 #include <asm/compiler.h>
+#include <asm/mce.h>
 
 /*
  * MCPCIA is the internal name for a core logic chipset which provides
index 91b46801b290420b067966382d1cd0be19d1d11b..ade9d92e68b40760dd31b6363d22e1be44ea73e8 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/compiler.h>
-#include <asm/system.h>
 
 /*
  * T2 is the internal name for the core logic chipset which provides
index da5449e22175235e1f91fe5150bf5289ccde55ba..968d9991f5ee2b06968c16359ce5618ce304e3c6 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_ALPHA_ELF_H
 
 #include <asm/auxvec.h>
+#include <asm/special_insns.h>
 
 /* Special values for the st_other field in the symbol table.  */
 
diff --git a/arch/alpha/include/asm/exec.h b/arch/alpha/include/asm/exec.h
new file mode 100644 (file)
index 0000000..4a5a41f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ALPHA_EXEC_H
+#define __ALPHA_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ALPHA_EXEC_H */
index ecb17a72acc3e5e1d44f46152da1e2d443c4e8cd..db00f7885faad8949db38886e5ebd798440f63f5 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_ALPHA_FPU_H
 #define __ASM_ALPHA_FPU_H
 
+#include <asm/special_insns.h>
+
 /*
  * Alpha floating-point control register defines:
  */
index 56ff96501350a3741a5621e1ab16590ac9056ab0..7a3d38d5ed6bb197b15048d49dc83fba5c7c9a76 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <asm/compiler.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machvec.h>
 #include <asm/hwrpb.h>
index 299bbc7e9d7168e43a7c87fa9699ef6e3d20ce33..ffb1726484af60125afb6056c81da3c3e7ed8527 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ALPHA_IRQFLAGS_H
 #define __ALPHA_IRQFLAGS_H
 
-#include <asm/system.h>
+#include <asm/pal.h>
 
 #define IPL_MIN                0
 #define IPL_SW0                1
diff --git a/arch/alpha/include/asm/mce.h b/arch/alpha/include/asm/mce.h
new file mode 100644 (file)
index 0000000..660285b
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __ALPHA_MCE_H
+#define __ALPHA_MCE_H
+
+/*
+ * This is the logout header that should be common to all platforms
+ * (assuming they are running OSF/1 PALcode, I guess).
+ */
+struct el_common {
+       unsigned int    size;           /* size in bytes of logout area */
+       unsigned int    sbz1    : 30;   /* should be zero */
+       unsigned int    err2    :  1;   /* second error */
+       unsigned int    retry   :  1;   /* retry flag */
+       unsigned int    proc_offset;    /* processor-specific offset */
+       unsigned int    sys_offset;     /* system-specific offset */
+       unsigned int    code;           /* machine check code */
+       unsigned int    frame_rev;      /* frame revision */
+};
+
+/* Machine Check Frame for uncorrectable errors (Large format)
+ *      --- This is used to log uncorrectable errors such as
+ *          double bit ECC errors.
+ *      --- These errors are detected by both processor and systems.
+ */
+struct el_common_EV5_uncorrectable_mcheck {
+        unsigned long   shadow[8];        /* Shadow reg. 8-14, 25           */
+        unsigned long   paltemp[24];      /* PAL TEMP REGS.                 */
+        unsigned long   exc_addr;         /* Address of excepting instruction*/
+        unsigned long   exc_sum;          /* Summary of arithmetic traps.   */
+        unsigned long   exc_mask;         /* Exception mask (from exc_sum). */
+        unsigned long   pal_base;         /* Base address for PALcode.      */
+        unsigned long   isr;              /* Interrupt Status Reg.          */
+        unsigned long   icsr;             /* CURRENT SETUP OF EV5 IBOX      */
+        unsigned long   ic_perr_stat;     /* I-CACHE Reg. <11> set Data parity
+                                                         <12> set TAG parity*/
+        unsigned long   dc_perr_stat;     /* D-CACHE error Reg. Bits set to 1:
+                                                     <2> Data error in bank 0
+                                                     <3> Data error in bank 1
+                                                     <4> Tag error in bank 0
+                                                     <5> Tag error in bank 1 */
+        unsigned long   va;               /* Effective VA of fault or miss. */
+        unsigned long   mm_stat;          /* Holds the reason for D-stream 
+                                             fault or D-cache parity errors */
+        unsigned long   sc_addr;          /* Address that was being accessed
+                                             when EV5 detected Secondary cache
+                                             failure.                 */
+        unsigned long   sc_stat;          /* Helps determine if the error was
+                                             TAG/Data parity(Secondary Cache)*/
+        unsigned long   bc_tag_addr;      /* Contents of EV5 BC_TAG_ADDR    */
+        unsigned long   ei_addr;          /* Physical address of any transfer
+                                             that is logged in EV5 EI_STAT */
+        unsigned long   fill_syndrome;    /* For correcting ECC errors.     */
+        unsigned long   ei_stat;          /* Helps identify reason of any 
+                                             processor uncorrectable error
+                                             at its external interface.     */
+        unsigned long   ld_lock;          /* Contents of EV5 LD_LOCK register*/
+};
+
+struct el_common_EV6_mcheck {
+       unsigned int FrameSize;         /* Bytes, including this field */
+       unsigned int FrameFlags;        /* <31> = Retry, <30> = Second Error */
+       unsigned int CpuOffset;         /* Offset to CPU-specific info */
+       unsigned int SystemOffset;      /* Offset to system-specific info */
+       unsigned int MCHK_Code;
+       unsigned int MCHK_Frame_Rev;
+       unsigned long I_STAT;           /* EV6 Internal Processor Registers */
+       unsigned long DC_STAT;          /* (See the 21264 Spec) */
+       unsigned long C_ADDR;
+       unsigned long DC1_SYNDROME;
+       unsigned long DC0_SYNDROME;
+       unsigned long C_STAT;
+       unsigned long C_STS;
+       unsigned long MM_STAT;
+       unsigned long EXC_ADDR;
+       unsigned long IER_CM;
+       unsigned long ISUM;
+       unsigned long RESERVED0;
+       unsigned long PAL_BASE;
+       unsigned long I_CTL;
+       unsigned long PCTX;
+};
+
+
+#endif /* __ALPHA_MCE_H */
index 86c08a02d2393fe3dc49bacbd6eec3e2e11a2f69..4c51c05333c604a0c7ea14216b8651dbba6ce926 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 1996, Linus Torvalds
  */
 
-#include <asm/system.h>
 #include <asm/machvec.h>
 #include <asm/compiler.h>
 #include <asm-generic/mm_hooks.h>
index 9b4ba0d6f00bae6294faad3da116c4bc28f3b4ef..6699ee58342988c4e4e93d6112969a52560f82cd 100644 (file)
 #define PAL_retsys     61
 #define PAL_rti                63
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+extern void halt(void) __attribute__((noreturn));
+#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
+
+#define imb() \
+__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
+
+#define draina() \
+__asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
+
+#define __CALL_PAL_R0(NAME, TYPE)                              \
+extern inline TYPE NAME(void)                                  \
+{                                                              \
+       register TYPE __r0 __asm__("$0");                       \
+       __asm__ __volatile__(                                   \
+               "call_pal %1 # " #NAME                          \
+               :"=r" (__r0)                                    \
+               :"i" (PAL_ ## NAME)                             \
+               :"$1", "$16", "$22", "$23", "$24", "$25");      \
+       return __r0;                                            \
+}
+
+#define __CALL_PAL_W1(NAME, TYPE0)                             \
+extern inline void NAME(TYPE0 arg0)                            \
+{                                                              \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %1 # "#NAME                           \
+               : "=r"(__r16)                                   \
+               : "i"(PAL_ ## NAME), "0"(__r16)                 \
+               : "$1", "$22", "$23", "$24", "$25");            \
+}
+
+#define __CALL_PAL_W2(NAME, TYPE0, TYPE1)                      \
+extern inline void NAME(TYPE0 arg0, TYPE1 arg1)                        \
+{                                                              \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       register TYPE1 __r17 __asm__("$17") = arg1;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %2 # "#NAME                           \
+               : "=r"(__r16), "=r"(__r17)                      \
+               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
+               : "$1", "$22", "$23", "$24", "$25");            \
+}
+
+#define __CALL_PAL_RW1(NAME, RTYPE, TYPE0)                     \
+extern inline RTYPE NAME(TYPE0 arg0)                           \
+{                                                              \
+       register RTYPE __r0 __asm__("$0");                      \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %2 # "#NAME                           \
+               : "=r"(__r16), "=r"(__r0)                       \
+               : "i"(PAL_ ## NAME), "0"(__r16)                 \
+               : "$1", "$22", "$23", "$24", "$25");            \
+       return __r0;                                            \
+}
+
+#define __CALL_PAL_RW2(NAME, RTYPE, TYPE0, TYPE1)              \
+extern inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1)               \
+{                                                              \
+       register RTYPE __r0 __asm__("$0");                      \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       register TYPE1 __r17 __asm__("$17") = arg1;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %3 # "#NAME                           \
+               : "=r"(__r16), "=r"(__r17), "=r"(__r0)          \
+               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
+               : "$1", "$22", "$23", "$24", "$25");            \
+       return __r0;                                            \
+}
+
+__CALL_PAL_W1(cflush, unsigned long);
+__CALL_PAL_R0(rdmces, unsigned long);
+__CALL_PAL_R0(rdps, unsigned long);
+__CALL_PAL_R0(rdusp, unsigned long);
+__CALL_PAL_RW1(swpipl, unsigned long, unsigned long);
+__CALL_PAL_R0(whami, unsigned long);
+__CALL_PAL_W2(wrent, void*, unsigned long);
+__CALL_PAL_W1(wripir, unsigned long);
+__CALL_PAL_W1(wrkgp, unsigned long);
+__CALL_PAL_W1(wrmces, unsigned long);
+__CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
+__CALL_PAL_W1(wrusp, unsigned long);
+__CALL_PAL_W1(wrvptptr, unsigned long);
+
+/*
+ * TB routines..
+ */
+#define __tbi(nr,arg,arg1...)                                  \
+({                                                             \
+       register unsigned long __r16 __asm__("$16") = (nr);     \
+       register unsigned long __r17 __asm__("$17"); arg;       \
+       __asm__ __volatile__(                                   \
+               "call_pal %3 #__tbi"                            \
+               :"=r" (__r16),"=r" (__r17)                      \
+               :"0" (__r16),"i" (PAL_tbi) ,##arg1              \
+               :"$0", "$1", "$22", "$23", "$24", "$25");       \
+})
+
+#define tbi(x,y)       __tbi(x,__r17=(y),"1" (__r17))
+#define tbisi(x)       __tbi(1,__r17=(x),"1" (__r17))
+#define tbisd(x)       __tbi(2,__r17=(x),"1" (__r17))
+#define tbis(x)                __tbi(3,__r17=(x),"1" (__r17))
+#define tbiap()                __tbi(-1, /* no second argument */)
+#define tbia()         __tbi(-2, /* no second argument */)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
 #endif /* __ALPHA_PAL_H */
index de98a732683d868b29a3175a5cccd6e22c23f1c8..81a4342d5a3f292866a992fda852bf880a14ccbc 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/page.h>
 #include <asm/processor.h>     /* For TASK_SIZE */
 #include <asm/machvec.h>
+#include <asm/setup.h>
 
 struct mm_struct;
 struct vm_area_struct;
index db167413300b263782adf8fb7105d1e501746878..24779fc95994efb5c4d69e4d507f3cba581570a4 100644 (file)
  */
 
 typedef unsigned int   __kernel_ino_t;
-typedef unsigned int   __kernel_mode_t;
-typedef unsigned int   __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef long long      __kernel_loff_t;
-typedef int            __kernel_pid_t;
-typedef int            __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
-typedef long           __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned long  __kernel_sigset_t;      /* at least 32 bits */
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_timer_t;
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
-
-typedef unsigned int   __kernel_old_dev_t;
-
-#ifdef __KERNEL__
-
-#ifndef __GNUC__
-
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define        __FD_ISSET(d, set)      (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
-#define        __FD_ZERO(set)  \
-  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
-
-#else /* __GNUC__ */
-
-/* With GNU C, use inline functions instead so args are evaluated only once: */
+#define __kernel_ino_t __kernel_ino_t
 
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, const __kernel_fd_set *p)
-{ 
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
-{
-       unsigned long *tmp = p->fds_bits;
-       int i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-                     case 16:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-                       tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                       return;
-
-                     case 8:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       return;
-
-                     case 4:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       return;
-               }
-       }
-       i = __FDSET_LONGS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
+typedef unsigned int   __kernel_nlink_t;
+#define __kernel_nlink_t __kernel_nlink_t
 
-#endif /* __GNUC__ */
+typedef unsigned long  __kernel_sigset_t;      /* at least 32 bits */
 
-#endif /* __KERNEL__ */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ALPHA_POSIX_TYPES_H */
index 2e023a4aa317e437283810a604f9c79ecb57c249..b50014b30909b4107b9e44688759e37018700582 100644 (file)
@@ -3,4 +3,40 @@
 
 #define COMMAND_LINE_SIZE      256
 
+/*
+ * We leave one page for the initial stack page, and one page for
+ * the initial process structure. Also, the console eats 3 MB for
+ * the initial bootloader (one of which we can reclaim later).
+ */
+#define BOOT_PCB       0x20000000
+#define BOOT_ADDR      0x20000000
+/* Remove when official MILO sources have ELF support: */
+#define BOOT_SIZE      (16*1024)
+
+#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
+#define KERNEL_START_PHYS      0x300000 /* Old bootloaders hardcoded this.  */
+#else
+#define KERNEL_START_PHYS      0x1000000 /* required: Wildfire/Titan/Marvel */
+#endif
+
+#define KERNEL_START   (PAGE_OFFSET+KERNEL_START_PHYS)
+#define SWAPPER_PGD    KERNEL_START
+#define INIT_STACK     (PAGE_OFFSET+KERNEL_START_PHYS+0x02000)
+#define EMPTY_PGT      (PAGE_OFFSET+KERNEL_START_PHYS+0x04000)
+#define EMPTY_PGE      (PAGE_OFFSET+KERNEL_START_PHYS+0x08000)
+#define ZERO_PGE       (PAGE_OFFSET+KERNEL_START_PHYS+0x0A000)
+
+#define START_ADDR     (PAGE_OFFSET+KERNEL_START_PHYS+0x10000)
+
+/*
+ * This is setup by the secondary bootstrap loader.  Because
+ * the zero page is zeroed out as soon as the vm system is
+ * initialized, we need to copy things out into a more permanent
+ * place.
+ */
+#define PARAM                  ZERO_PGE
+#define COMMAND_LINE           ((char*)(PARAM + 0x0000))
+#define INITRD_START           (*(unsigned long *) (PARAM+0x100))
+#define INITRD_SIZE            (*(unsigned long *) (PARAM+0x108))
+
 #endif
diff --git a/arch/alpha/include/asm/special_insns.h b/arch/alpha/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..88d3452
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __ALPHA_SPECIAL_INSNS_H
+#define __ALPHA_SPECIAL_INSNS_H
+
+enum implver_enum {
+       IMPLVER_EV4,
+       IMPLVER_EV5,
+       IMPLVER_EV6
+};
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define implver()                              \
+({ unsigned long __implver;                    \
+   __asm__ ("implver %0" : "=r"(__implver));   \
+   (enum implver_enum) __implver; })
+#else
+/* Try to eliminate some dead code.  */
+#ifdef CONFIG_ALPHA_EV4
+#define implver() IMPLVER_EV4
+#endif
+#ifdef CONFIG_ALPHA_EV5
+#define implver() IMPLVER_EV5
+#endif
+#if defined(CONFIG_ALPHA_EV6)
+#define implver() IMPLVER_EV6
+#endif
+#endif
+
+enum amask_enum {
+       AMASK_BWX = (1UL << 0),
+       AMASK_FIX = (1UL << 1),
+       AMASK_CIX = (1UL << 2),
+       AMASK_MAX = (1UL << 8),
+       AMASK_PRECISE_TRAP = (1UL << 9),
+};
+
+#define amask(mask)                                            \
+({ unsigned long __amask, __input = (mask);                    \
+   __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input));    \
+   __amask; })
+
+#endif /* __ALPHA_SPECIAL_INSNS_H */
index d0faca1e992df0ffc9ca0ed12408e132da9b798a..3bba21e41b818e1ff8fb7f346721dc8e95f93950 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_SPINLOCK_H
 #define _ALPHA_SPINLOCK_H
 
-#include <asm/system.h>
 #include <linux/kernel.h>
 #include <asm/current.h>
 
diff --git a/arch/alpha/include/asm/switch_to.h b/arch/alpha/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..44c0d4f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ALPHA_SWITCH_TO_H
+#define __ALPHA_SWITCH_TO_H
+
+
+struct task_struct;
+extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct *);
+
+#define switch_to(P,N,L)                                                \
+  do {                                                                  \
+    (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \
+    check_mmu_context();                                                \
+  } while (0)
+
+#endif /* __ALPHA_SWITCH_TO_H */
diff --git a/arch/alpha/include/asm/system.h b/arch/alpha/include/asm/system.h
deleted file mode 100644 (file)
index 9f78e69..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-#ifndef __ALPHA_SYSTEM_H
-#define __ALPHA_SYSTEM_H
-
-#include <asm/pal.h>
-#include <asm/page.h>
-#include <asm/barrier.h>
-
-/*
- * System defines.. Note that this is included both from .c and .S
- * files, so it does only defines, not any C code.
- */
-
-/*
- * We leave one page for the initial stack page, and one page for
- * the initial process structure. Also, the console eats 3 MB for
- * the initial bootloader (one of which we can reclaim later).
- */
-#define BOOT_PCB       0x20000000
-#define BOOT_ADDR      0x20000000
-/* Remove when official MILO sources have ELF support: */
-#define BOOT_SIZE      (16*1024)
-
-#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
-#define KERNEL_START_PHYS      0x300000 /* Old bootloaders hardcoded this.  */
-#else
-#define KERNEL_START_PHYS      0x1000000 /* required: Wildfire/Titan/Marvel */
-#endif
-
-#define KERNEL_START   (PAGE_OFFSET+KERNEL_START_PHYS)
-#define SWAPPER_PGD    KERNEL_START
-#define INIT_STACK     (PAGE_OFFSET+KERNEL_START_PHYS+0x02000)
-#define EMPTY_PGT      (PAGE_OFFSET+KERNEL_START_PHYS+0x04000)
-#define EMPTY_PGE      (PAGE_OFFSET+KERNEL_START_PHYS+0x08000)
-#define ZERO_PGE       (PAGE_OFFSET+KERNEL_START_PHYS+0x0A000)
-
-#define START_ADDR     (PAGE_OFFSET+KERNEL_START_PHYS+0x10000)
-
-/*
- * This is setup by the secondary bootstrap loader.  Because
- * the zero page is zeroed out as soon as the vm system is
- * initialized, we need to copy things out into a more permanent
- * place.
- */
-#define PARAM                  ZERO_PGE
-#define COMMAND_LINE           ((char*)(PARAM + 0x0000))
-#define INITRD_START           (*(unsigned long *) (PARAM+0x100))
-#define INITRD_SIZE            (*(unsigned long *) (PARAM+0x108))
-
-#ifndef __ASSEMBLY__
-#include <linux/kernel.h>
-#define AT_VECTOR_SIZE_ARCH 4 /* entries in ARCH_DLINFO */
-
-/*
- * This is the logout header that should be common to all platforms
- * (assuming they are running OSF/1 PALcode, I guess).
- */
-struct el_common {
-       unsigned int    size;           /* size in bytes of logout area */
-       unsigned int    sbz1    : 30;   /* should be zero */
-       unsigned int    err2    :  1;   /* second error */
-       unsigned int    retry   :  1;   /* retry flag */
-       unsigned int    proc_offset;    /* processor-specific offset */
-       unsigned int    sys_offset;     /* system-specific offset */
-       unsigned int    code;           /* machine check code */
-       unsigned int    frame_rev;      /* frame revision */
-};
-
-/* Machine Check Frame for uncorrectable errors (Large format)
- *      --- This is used to log uncorrectable errors such as
- *          double bit ECC errors.
- *      --- These errors are detected by both processor and systems.
- */
-struct el_common_EV5_uncorrectable_mcheck {
-        unsigned long   shadow[8];        /* Shadow reg. 8-14, 25           */
-        unsigned long   paltemp[24];      /* PAL TEMP REGS.                 */
-        unsigned long   exc_addr;         /* Address of excepting instruction*/
-        unsigned long   exc_sum;          /* Summary of arithmetic traps.   */
-        unsigned long   exc_mask;         /* Exception mask (from exc_sum). */
-        unsigned long   pal_base;         /* Base address for PALcode.      */
-        unsigned long   isr;              /* Interrupt Status Reg.          */
-        unsigned long   icsr;             /* CURRENT SETUP OF EV5 IBOX      */
-        unsigned long   ic_perr_stat;     /* I-CACHE Reg. <11> set Data parity
-                                                         <12> set TAG parity*/
-        unsigned long   dc_perr_stat;     /* D-CACHE error Reg. Bits set to 1:
-                                                     <2> Data error in bank 0
-                                                     <3> Data error in bank 1
-                                                     <4> Tag error in bank 0
-                                                     <5> Tag error in bank 1 */
-        unsigned long   va;               /* Effective VA of fault or miss. */
-        unsigned long   mm_stat;          /* Holds the reason for D-stream 
-                                             fault or D-cache parity errors */
-        unsigned long   sc_addr;          /* Address that was being accessed
-                                             when EV5 detected Secondary cache
-                                             failure.                 */
-        unsigned long   sc_stat;          /* Helps determine if the error was
-                                             TAG/Data parity(Secondary Cache)*/
-        unsigned long   bc_tag_addr;      /* Contents of EV5 BC_TAG_ADDR    */
-        unsigned long   ei_addr;          /* Physical address of any transfer
-                                             that is logged in EV5 EI_STAT */
-        unsigned long   fill_syndrome;    /* For correcting ECC errors.     */
-        unsigned long   ei_stat;          /* Helps identify reason of any 
-                                             processor uncorrectable error
-                                             at its external interface.     */
-        unsigned long   ld_lock;          /* Contents of EV5 LD_LOCK register*/
-};
-
-struct el_common_EV6_mcheck {
-       unsigned int FrameSize;         /* Bytes, including this field */
-       unsigned int FrameFlags;        /* <31> = Retry, <30> = Second Error */
-       unsigned int CpuOffset;         /* Offset to CPU-specific info */
-       unsigned int SystemOffset;      /* Offset to system-specific info */
-       unsigned int MCHK_Code;
-       unsigned int MCHK_Frame_Rev;
-       unsigned long I_STAT;           /* EV6 Internal Processor Registers */
-       unsigned long DC_STAT;          /* (See the 21264 Spec) */
-       unsigned long C_ADDR;
-       unsigned long DC1_SYNDROME;
-       unsigned long DC0_SYNDROME;
-       unsigned long C_STAT;
-       unsigned long C_STS;
-       unsigned long MM_STAT;
-       unsigned long EXC_ADDR;
-       unsigned long IER_CM;
-       unsigned long ISUM;
-       unsigned long RESERVED0;
-       unsigned long PAL_BASE;
-       unsigned long I_CTL;
-       unsigned long PCTX;
-};
-
-extern void halt(void) __attribute__((noreturn));
-#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
-
-#define switch_to(P,N,L)                                                \
-  do {                                                                  \
-    (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \
-    check_mmu_context();                                                \
-  } while (0)
-
-struct task_struct;
-extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct*);
-
-#define imb() \
-__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
-
-#define draina() \
-__asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
-
-enum implver_enum {
-       IMPLVER_EV4,
-       IMPLVER_EV5,
-       IMPLVER_EV6
-};
-
-#ifdef CONFIG_ALPHA_GENERIC
-#define implver()                              \
-({ unsigned long __implver;                    \
-   __asm__ ("implver %0" : "=r"(__implver));   \
-   (enum implver_enum) __implver; })
-#else
-/* Try to eliminate some dead code.  */
-#ifdef CONFIG_ALPHA_EV4
-#define implver() IMPLVER_EV4
-#endif
-#ifdef CONFIG_ALPHA_EV5
-#define implver() IMPLVER_EV5
-#endif
-#if defined(CONFIG_ALPHA_EV6)
-#define implver() IMPLVER_EV6
-#endif
-#endif
-
-enum amask_enum {
-       AMASK_BWX = (1UL << 0),
-       AMASK_FIX = (1UL << 1),
-       AMASK_CIX = (1UL << 2),
-       AMASK_MAX = (1UL << 8),
-       AMASK_PRECISE_TRAP = (1UL << 9),
-};
-
-#define amask(mask)                                            \
-({ unsigned long __amask, __input = (mask);                    \
-   __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input));    \
-   __amask; })
-
-#define __CALL_PAL_R0(NAME, TYPE)                              \
-extern inline TYPE NAME(void)                                  \
-{                                                              \
-       register TYPE __r0 __asm__("$0");                       \
-       __asm__ __volatile__(                                   \
-               "call_pal %1 # " #NAME                          \
-               :"=r" (__r0)                                    \
-               :"i" (PAL_ ## NAME)                             \
-               :"$1", "$16", "$22", "$23", "$24", "$25");      \
-       return __r0;                                            \
-}
-
-#define __CALL_PAL_W1(NAME, TYPE0)                             \
-extern inline void NAME(TYPE0 arg0)                            \
-{                                                              \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %1 # "#NAME                           \
-               : "=r"(__r16)                                   \
-               : "i"(PAL_ ## NAME), "0"(__r16)                 \
-               : "$1", "$22", "$23", "$24", "$25");            \
-}
-
-#define __CALL_PAL_W2(NAME, TYPE0, TYPE1)                      \
-extern inline void NAME(TYPE0 arg0, TYPE1 arg1)                        \
-{                                                              \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       register TYPE1 __r17 __asm__("$17") = arg1;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %2 # "#NAME                           \
-               : "=r"(__r16), "=r"(__r17)                      \
-               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
-               : "$1", "$22", "$23", "$24", "$25");            \
-}
-
-#define __CALL_PAL_RW1(NAME, RTYPE, TYPE0)                     \
-extern inline RTYPE NAME(TYPE0 arg0)                           \
-{                                                              \
-       register RTYPE __r0 __asm__("$0");                      \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %2 # "#NAME                           \
-               : "=r"(__r16), "=r"(__r0)                       \
-               : "i"(PAL_ ## NAME), "0"(__r16)                 \
-               : "$1", "$22", "$23", "$24", "$25");            \
-       return __r0;                                            \
-}
-
-#define __CALL_PAL_RW2(NAME, RTYPE, TYPE0, TYPE1)              \
-extern inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1)               \
-{                                                              \
-       register RTYPE __r0 __asm__("$0");                      \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       register TYPE1 __r17 __asm__("$17") = arg1;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %3 # "#NAME                           \
-               : "=r"(__r16), "=r"(__r17), "=r"(__r0)          \
-               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
-               : "$1", "$22", "$23", "$24", "$25");            \
-       return __r0;                                            \
-}
-
-__CALL_PAL_W1(cflush, unsigned long);
-__CALL_PAL_R0(rdmces, unsigned long);
-__CALL_PAL_R0(rdps, unsigned long);
-__CALL_PAL_R0(rdusp, unsigned long);
-__CALL_PAL_RW1(swpipl, unsigned long, unsigned long);
-__CALL_PAL_R0(whami, unsigned long);
-__CALL_PAL_W2(wrent, void*, unsigned long);
-__CALL_PAL_W1(wripir, unsigned long);
-__CALL_PAL_W1(wrkgp, unsigned long);
-__CALL_PAL_W1(wrmces, unsigned long);
-__CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
-__CALL_PAL_W1(wrusp, unsigned long);
-__CALL_PAL_W1(wrvptptr, unsigned long);
-
-/*
- * TB routines..
- */
-#define __tbi(nr,arg,arg1...)                                  \
-({                                                             \
-       register unsigned long __r16 __asm__("$16") = (nr);     \
-       register unsigned long __r17 __asm__("$17"); arg;       \
-       __asm__ __volatile__(                                   \
-               "call_pal %3 #__tbi"                            \
-               :"=r" (__r16),"=r" (__r17)                      \
-               :"0" (__r16),"i" (PAL_tbi) ,##arg1              \
-               :"$0", "$1", "$22", "$23", "$24", "$25");       \
-})
-
-#define tbi(x,y)       __tbi(x,__r17=(y),"1" (__r17))
-#define tbisi(x)       __tbi(1,__r17=(x),"1" (__r17))
-#define tbisd(x)       __tbi(2,__r17=(x),"1" (__r17))
-#define tbis(x)                __tbi(3,__r17=(x),"1" (__r17))
-#define tbiap()                __tbi(-1, /* no second argument */)
-#define tbia()         __tbi(-2, /* no second argument */)
-
-/*
- * Atomic exchange routines.
- */
-
-#define __ASM__MB
-#define ____xchg(type, args...)                __xchg ## type ## _local(args)
-#define ____cmpxchg(type, args...)     __cmpxchg ## type ## _local(args)
-#include <asm/xchg.h>
-
-#define xchg_local(ptr,x)                                              \
-  ({                                                                   \
-     __typeof__(*(ptr)) _x_ = (x);                                     \
-     (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,      \
-                                      sizeof(*(ptr)));                 \
-  })
-
-#define cmpxchg_local(ptr, o, n)                                       \
-  ({                                                                   \
-     __typeof__(*(ptr)) _o_ = (o);                                     \
-     __typeof__(*(ptr)) _n_ = (n);                                     \
-     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,   \
-                                         (unsigned long)_n_,           \
-                                         sizeof(*(ptr)));              \
-  })
-
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-
-#ifdef CONFIG_SMP
-#undef __ASM__MB
-#define __ASM__MB      "\tmb\n"
-#endif
-#undef ____xchg
-#undef ____cmpxchg
-#define ____xchg(type, args...)                __xchg ##type(args)
-#define ____cmpxchg(type, args...)     __cmpxchg ##type(args)
-#include <asm/xchg.h>
-
-#define xchg(ptr,x)                                                    \
-  ({                                                                   \
-     __typeof__(*(ptr)) _x_ = (x);                                     \
-     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_,            \
-                                sizeof(*(ptr)));                       \
-  })
-
-#define cmpxchg(ptr, o, n)                                             \
-  ({                                                                   \
-     __typeof__(*(ptr)) _o_ = (o);                                     \
-     __typeof__(*(ptr)) _n_ = (n);                                     \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,         \
-                                   (unsigned long)_n_, sizeof(*(ptr)));\
-  })
-
-#define cmpxchg64(ptr, o, n)                                           \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg((ptr), (o), (n));                                       \
-  })
-
-#undef __ASM__MB
-#undef ____cmpxchg
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif
index beba1b803e0d85f6817dbc3f27306c7808e6ddde..1d1b436fbff252bc867c8e577c7b8759bc55cc20 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef __ALPHA_SYSTEM_H
+#ifndef _ALPHA_ATOMIC_H
 #error Do not include xchg.h directly!
 #else
 /*
index ca46b2c2445756bfc84cfd87ee5fe58226c6bec0..708c831efa76594a1cd2299b7d3214f06f3ccc69 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/smp.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "pci_impl.h"
index 1d6ee6c985f940992db550fdb5595945c6597611..c44339e176c163718ae7cc33cd4b762210ea77c2 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/bootmem.h>
 
 #include <asm/ptrace.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "pci_impl.h"
index 2f770e99428961f6233c8d7742f705180455bdb2..3ada4f7b085d42987dbb14bd0d78af2311935d9a 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/delay.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "pci_impl.h"
index 0c010ca4611ea85ab244857d68199638ef768766..ae529c4160374ab1a280bd2a934db6118499768b 100644 (file)
@@ -7,6 +7,8 @@
  *     implementations.
  */
 
+#include <asm/mce.h>
+
 union el_timestamp;
 struct el_subpacket;
 struct ev7_lf_subpackets;
index 4bdd1d2ff353dfd6b4bf8fde957b904e99e4e811..c352499ab9f8d1432fbfea07e8e69dee411e153d 100644 (file)
@@ -8,14 +8,12 @@
  */
 
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/asm-offsets.h>
+#include <asm/pal.h>
+#include <asm/setup.h>
 
 __HEAD
-.globl swapper_pg_dir
 .globl _stext
-swapper_pg_dir=SWAPPER_PGD
-
        .set noreorder
        .globl  __start
        .ent    __start
index 381431a2d6d9d7be7703bfe424e08759df56c8d3..2872accd22156b7ee134f70c84376a7dff48a4c8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/profile.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 51b7fbd9e4c11406ce8950f6cecc64f1ebd7556a..772ddfdb71a8e67af8f20e38ff7f8def9af3b943 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/machvec.h>
 #include <asm/dma.h>
 #include <asm/perf_event.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "irq_impl.h"
index 01e8715e26d9306148a8706d046cf863015c1721..49ee3193477aff3c372f3c2372cdb461a89d37ab 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/fpu.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/sysinfo.h>
 #include <asm/thread_info.h>
 #include <asm/hwrpb.h>
index 89bbe5b4114510e07c187000152ba76930aa5ebf..153d3fce3e8e9b4adc84c64fe63483d815a1ec59 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/reg.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
index e2af5eb59bb432ad870b2d2a08d46a74e97c82fe..54616f496aedb27629d298329a43ff8447113300 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 
 #include "proto.h"
index 32de56067e63db5ed8ea6941df1de97540b412b6..9e3107cc5ebb45d7dccc2889462f9f10c4b575ec 100644 (file)
@@ -55,7 +55,6 @@ static struct notifier_block alpha_panic_block = {
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
 #include <asm/mmu_context.h>
index 8606d77e5163355e280c1f6ac7d040724cd69bc5..118dc6af1805098e1f69439b07dc4885627a21d6 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/mmu_context.h>
index 1029619fb6c0770de71da08028004805135aa7fc..4c50f8f40cbbfe73c39ffd0062d1937dd892b9a6 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 13f0717fc7fe314d6a3f9df62bb57a36abc92b95..5bf401f7ea97f5379067facc21762c9dfdd1732d 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 3c6c13cd8b19ff39b395ee02dda443a593a97d47..ad40a425e841c2f1c99904a43c45fa2c9a281d1d 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 35f480db7719605eb8743b9ce467231846c46948..79d69d7f63f8901dfd8f37b33069e57876d30919 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 7f1a87f176e25d469762851370e0e92c3cc813f4..5a0af11b3a61c1b97b5e1da19fe1fb8f2dd15f50 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
index fc8b125086115f7bd2e66e210dfb24753d5d2f13..14a4b6a7cf59d3fa94b121714c7e3c67792618e8 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 258da684670b34bba8fbec093e365d38e2cf45b3..d5b9776a608d91d957b8a362c3da3e8c93ccaad5 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/reboot.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index c0fd7284dec318beba90ece97475de61ba48860e..5e82dc1ad6f2dc096cdc217f9c32f46180c6a7a6 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 4112200307c73eac73f6bff9ccf10a534b1c16b6..4d4c046f708d6f4691388b64fdd3bd014bb3b3c5 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 21725283cdd7dac5847c25ae7ec07c115afd3c69..063e594fd96934f90971172c25f84fc8e9a89255 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index a125d6bea7e1d97a665f6db6c337109f560d7730..dfd510ae5d8c82701b5a5fbf278bc0af699d56a5 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 2581cbec6fc21bce1625677a5e58fd52a2db4287..a3f4852571700183d033126a8b82ff46613c2943 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index b172b27555a768006b6b3151bec8c923ba4d2cb3..08ee737d4fba1559c6fe09ce2cb7a98e2fc23ffe 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 98d1dbffe98f546667c55587e19145dc31de4c63..8a0aa6d67b5319c18d9ba050f4d6364d4108dc5b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 47bec1e97d1ca9e0cbdbb4bde0c75cb9d3e06dcf..febd24eba7a6a26d7251dfdd85473d00b531669a 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <asm/compiler.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 73e1c317afcb4f86870a4a8ab026dd09ad61ec8c..d063b360efedc49d7690af17d87d39a93205f56d 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
@@ -26,6 +25,7 @@
 #include <asm/core_cia.h>
 #include <asm/hwrpb.h>
 #include <asm/tlbflush.h>
+#include <asm/special_insns.h>
 
 #include "proto.h"
 #include "irq_impl.h"
index 2ae99ad6975e270513eabfd07f024d6b5f818b86..dd0f1eae3c68d27122718485760ce2f2db276bf2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index b8eafa053539005d7ddd0bffb4ee293cd5910891..2533db280d9ba1f7ea642d4c947b5d532484a526 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 17c85a65e7b0307e5741d0c395ac392719773a80..ee1874887776bd5c732ce6c964cbe8cb7154d8ef 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 0414e021a91c3ba8756674dea873f0dabd6c0abd..80d987c0e9aa55889aa3b8ed5d8a25fe9309b1c2 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/sysinfo.h>
 #include <asm/hwrpb.h>
 #include <asm/mmu_context.h>
+#include <asm/special_insns.h>
 
 #include "proto.h"
 
index f937ad12385273ab0d97c49648fa30dad325d940..647b84c15382347ec25efae55067e77fff26693e 100644 (file)
@@ -2,6 +2,7 @@
 #include <asm/thread_info.h>
 #include <asm/cache.h>
 #include <asm/page.h>
+#include <asm/setup.h>
 
 OUTPUT_FORMAT("elf64-alpha")
 OUTPUT_ARCH(alpha)
@@ -25,6 +26,7 @@ SECTIONS
                *(.fixup)
                *(.gnu.warning)
        } :kernel
+       swapper_pg_dir = SWAPPER_PGD;
        _etext = .;     /* End of text section */
 
        NOTES :kernel :note
index 6d432e42aedceda0d70f6063902c90b77a0a92d0..5e832161e6d2ff00fc7c83b3e2d7361347d67c3c 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <asm/system.h>
 
 typedef unsigned int instr;
 
index fadd5f882ff9182e89bb8fdddbed626b8a4a5c1d..5eecab1a84efd3430deab218698ab3dab91c0e6a 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
index 69d0c5761e2f206d5de46da70703ca22e940ed08..1ad6ca74bed2f5433979a477bbe90db81ddd3d8b 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/vmalloc.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -31,6 +30,7 @@
 #include <asm/mmu_context.h>
 #include <asm/console.h>
 #include <asm/tlb.h>
+#include <asm/setup.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
index bd8ac533a504d96521507df11795d9e0cd032118..a0a5d27aa2150e48c840cfcdae78f43f5bc8c4dd 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 80d764dbf22f04dd2d373a8ea1608b9c45447ffb..18aa9b4f94f1822be3e01ea0906fd2cf234c1205 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index ceea6e1ad79aedf61123f5c5f5930a42c75fe0f1..c32f8a0ad92543a0d6e6767e698f51da0972c17e 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 0869f85f57489db358b0fc75a073ae2248a2e9d5..1c84cc257fc7ec7a6c3df970722b381f0ed17ff3 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 5b9d178e0228e5b702fd1487c875511cb3c91715..34a57a12655377727930f8abba88082f3afde149 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 5098564d58799cc8c63e222003a6881a44c509af..93180845ae164dbeeca41a27dfce6fda553bcb3d 100644 (file)
@@ -9,6 +9,7 @@ config ARM
        select SYS_SUPPORTS_APM_EMULATION
        select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
        select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
+       select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
        select HAVE_ARCH_KGDB
        select HAVE_KPROBES if !XIP_KERNEL
        select HAVE_KRETPROBES if (HAVE_KPROBES)
@@ -21,6 +22,7 @@ config ARM
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
+       select HAVE_KERNEL_XZ
        select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
@@ -28,10 +30,10 @@ config ARM
        select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
        select HAVE_C_RECORDMCOUNT
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
        select GENERIC_IRQ_SHOW
        select CPU_PM if (SUSPEND || CPU_IDLE)
        select GENERIC_PCI_IOMAP
+       select HAVE_BPF_JIT if NET
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -52,9 +54,6 @@ config MIGHT_HAVE_PCI
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
-config HAVE_SCHED_CLOCK
-       bool
-
 config GENERIC_GPIO
        bool
 
@@ -180,6 +179,9 @@ config ZONE_DMA
 config NEED_DMA_MAP_STATE
        def_bool y
 
+config ARCH_HAS_DMA_SET_COHERENT_MASK
+       bool
+
 config GENERIC_ISA_DMA
        bool
 
@@ -217,6 +219,13 @@ config ARM_PATCH_PHYS_VIRT
          this feature (eg, building a kernel for a single machine) and
          you need to shrink the kernel to the minimal size.
 
+config NEED_MACH_IO_H
+       bool
+       help
+         Select this when mach/io.h is required to provide special
+         definitions for this platform.  The need for mach/io.h should
+         be avoided when possible.
+
 config NEED_MACH_MEMORY_H
        bool
        help
@@ -268,7 +277,9 @@ config ARCH_INTEGRATOR
        select GENERIC_CLOCKEVENTS
        select PLAT_VERSATILE
        select PLAT_VERSATILE_FPGA_IRQ
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
+       select SPARSE_IRQ
        help
          Support for ARM's Integrator platform.
 
@@ -315,6 +326,7 @@ config ARCH_VEXPRESS
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
        select ICST
+       select NO_IOPORT
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLCD
        help
@@ -354,6 +366,7 @@ config ARCH_HIGHBANK
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU
        select HAVE_SMP
+       select SPARSE_IRQ
        select USE_OF
        help
          Support for the Calxeda Highbank SoC based boards.
@@ -404,6 +417,7 @@ config ARCH_EBSA110
        select ISA
        select NO_IOPORT
        select ARCH_USES_GETTIMEOFFSET
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        help
          This is an evaluation board for the StrongARM processor available
@@ -430,6 +444,7 @@ config ARCH_FOOTBRIDGE
        select FOOTBRIDGE
        select GENERIC_CLOCKEVENTS
        select HAVE_IDE
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        help
          Support for systems based on the DC21285 companion chip
@@ -442,7 +457,6 @@ config ARCH_MXC
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
-       select HAVE_SCHED_CLOCK
        select MULTI_IRQ_HANDLER
        help
          Support for Freescale MXC/iMX-based family of processors
@@ -482,6 +496,7 @@ config ARCH_IOP13XX
        select PCI
        select ARCH_SUPPORTS_MSI
        select VMSPLIT_1G
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        select NEED_RET_TO_USER
        help
@@ -491,6 +506,7 @@ config ARCH_IOP32X
        bool "IOP32x-based"
        depends on MMU
        select CPU_XSCALE
+       select NEED_MACH_IO_H
        select NEED_RET_TO_USER
        select PLAT_IOP
        select PCI
@@ -503,6 +519,7 @@ config ARCH_IOP33X
        bool "IOP33x-based"
        depends on MMU
        select CPU_XSCALE
+       select NEED_MACH_IO_H
        select NEED_RET_TO_USER
        select PLAT_IOP
        select PCI
@@ -516,6 +533,7 @@ config ARCH_IXP23XX
        select CPU_XSC3
        select PCI
        select ARCH_USES_GETTIMEOFFSET
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        help
          Support for Intel's IXP23xx (XScale) family of processors.
@@ -526,6 +544,7 @@ config ARCH_IXP2000
        select CPU_XSCALE
        select PCI
        select ARCH_USES_GETTIMEOFFSET
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        help
          Support for Intel's IXP2400/2800 (XScale) family of processors.
@@ -533,12 +552,13 @@ config ARCH_IXP2000
 config ARCH_IXP4XX
        bool "IXP4xx-based"
        depends on MMU
+       select ARCH_HAS_DMA_SET_COHERENT_MASK
        select CLKSRC_MMIO
        select CPU_XSCALE
        select GENERIC_GPIO
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select MIGHT_HAVE_PCI
+       select NEED_MACH_IO_H
        select DMABOUNCE if PCI
        help
          Support for Intel's IXP4XX (XScale) family of processors.
@@ -549,6 +569,7 @@ config ARCH_DOVE
        select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
+       select NEED_MACH_IO_H
        select PLAT_ORION
        help
          Support for the Marvell Dove SoC 88AP510
@@ -559,6 +580,7 @@ config ARCH_KIRKWOOD
        select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
+       select NEED_MACH_IO_H
        select PLAT_ORION
        help
          Support for the following Marvell Kirkwood series SoCs:
@@ -583,6 +605,7 @@ config ARCH_MV78XX0
        select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
+       select NEED_MACH_IO_H
        select PLAT_ORION
        help
          Support for the following Marvell MV78xx0 series SoCs:
@@ -608,7 +631,6 @@ config ARCH_MMP
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select GPIO_PXA
-       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
@@ -649,9 +671,9 @@ config ARCH_TEGRA
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_CLK
-       select HAVE_SCHED_CLOCK
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
+       select NEED_MACH_IO_H if PCI
        select ARCH_HAS_CPUFREQ
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
@@ -666,7 +688,6 @@ config ARCH_PICOXCELL
        select DW_APB_TIMER
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
-       select HAVE_SCHED_CLOCK
        select HAVE_TCM
        select NO_IOPORT
        select SPARSE_IRQ
@@ -694,7 +715,6 @@ config ARCH_PXA
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select GPIO_PXA
-       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
@@ -745,6 +765,7 @@ config ARCH_RPC
        select ARCH_SPARSEMEM_ENABLE
        select ARCH_USES_GETTIMEOFFSET
        select HAVE_IDE
+       select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        help
          On the Acorn Risc-PC, Linux can support the internal IDE disk and
@@ -761,7 +782,6 @@ config ARCH_SA1100
        select CPU_FREQ
        select GENERIC_CLOCKEVENTS
        select CLKDEV_LOOKUP
-       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select ARCH_REQUIRE_GPIOLIB
        select HAVE_IDE
@@ -780,6 +800,7 @@ config ARCH_S3C24XX
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C_RTC if RTC_CLASS
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
+       select NEED_MACH_IO_H
        help
          Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443
          and S3C2450 SoCs based systems, such as the Simtec Electronics BAST
@@ -818,7 +839,6 @@ config ARCH_S5P64X0
        select CLKSRC_MMIO
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C_RTC if RTC_CLASS
        help
@@ -849,7 +869,6 @@ config ARCH_S5PV210
        select CLKSRC_MMIO
        select ARCH_HAS_CPUFREQ
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C_RTC if RTC_CLASS
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -883,6 +902,7 @@ config ARCH_SHARK
        select PCI
        select ARCH_USES_GETTIMEOFFSET
        select NEED_MACH_MEMORY_H
+       select NEED_MACH_IO_H
        help
          Support for the StrongARM based Digital DNARD machine, also known
          as "Shark" (<http://www.shark-linux.de/shark.html>).
@@ -892,7 +912,6 @@ config ARCH_U300
        depends on MMU
        select CLKSRC_MMIO
        select CPU_ARM926T
-       select HAVE_SCHED_CLOCK
        select HAVE_TCM
        select ARM_AMBA
        select ARM_PATCH_PHYS_VIRT
@@ -951,7 +970,6 @@ config ARCH_OMAP
        select ARCH_HAS_CPUFREQ
        select CLKSRC_MMIO
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
          Support for TI's OMAP platform (OMAP1/2/3/4).
@@ -1115,13 +1133,11 @@ config ARCH_ACORN
 config PLAT_IOP
        bool
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
 
 config PLAT_ORION
        bool
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
-       select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
        bool
index 66ca8014ff3e6648fcb353923e39ee4663d3edc4..85348a09d655afc220fc55f71810b07830ea8936 100644 (file)
@@ -292,6 +292,22 @@ choice
                  Note that the system will appear to hang during boot if there
                  is nothing connected to read from the DCC.
 
+       config DEBUG_SEMIHOSTING
+               bool "Kernel low-level debug output via semihosting I"
+               help
+                 Semihosting enables code running on an ARM target to use
+                 the I/O facilities on a host debugger/emulator through a
+                 simple SVC calls. The host debugger or emulator must have
+                 semihosting enabled for the special svc call to be trapped
+                 otherwise the kernel will crash.
+
+                 This is known to work with OpenOCD, as wellas
+                 ARM's Fast Models, or any other controlling environment
+                 that implements semihosting.
+
+                 For more details about semihosting, please see
+                 chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd.
+
 endchoice
 
 config EARLY_PRINTK
index dcb088e868feaa02eb039947cf658b692a7ed0bc..047a20780fc15a5b753c3ea80c2178efed29c18c 100644 (file)
@@ -253,6 +253,7 @@ core-$(CONFIG_VFP)          += arch/arm/vfp/
 
 # If we have a machine-specific directory, then include it in the build.
 core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y                         += arch/arm/net/
 core-y                         += $(machdirs) $(platdirs)
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
index e0936a148516e2c5005d3620065938b4acec8b11..d0d441c429ae3e4e6c438fad1c51c7079c6eda5b 100644 (file)
@@ -1,8 +1,10 @@
+ashldi3.S
 font.c
 lib1funcs.S
 piggy.gzip
 piggy.lzo
 piggy.lzma
+piggy.xzkern
 vmlinux
 vmlinux.lds
 
index cf0a64ce4b83ad73b21b5cd6d59ab4c96fc5f2f3..bb267562e7ed9a763218c83eaeb2c5c8645debb9 100644 (file)
@@ -92,6 +92,7 @@ SEDFLAGS      = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
+suffix_$(CONFIG_KERNEL_XZ)   = xzkern
 
 # Borrowed libfdt files for the ATAG compatibility mode
 
@@ -112,10 +113,12 @@ endif
 
 targets       := vmlinux vmlinux.lds \
                 piggy.$(suffix_y) piggy.$(suffix_y).o \
-                lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
+                lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S \
+                font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
+extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \
+                lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -151,6 +154,12 @@ lib1funcs = $(obj)/lib1funcs.o
 $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
        $(call cmd,shipped)
 
+# For __aeabi_llsl
+ashldi3 = $(obj)/ashldi3.o
+
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S
+       $(call cmd,shipped)
+
 # We need to prevent any GOTOFF relocs being used with references
 # to symbols in the .bss section since we cannot relocate them
 # independently from the rest at run time.  This can be achieved by
@@ -172,7 +181,7 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
 fi
 
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
-               $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+               $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
        @$(check_for_multiple_zreladdr)
        $(call if_changed,ld)
        @$(check_for_bad_syms)
index 07be5a2f830236736b15022da52fa0362ff5c16f..f41b38cafce80b046217364df5947926dfccf46b 100644 (file)
@@ -44,6 +44,12 @@ extern void error(char *);
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#define memmove memmove
+#define memcpy memcpy
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
 {
        return decompress(input, len, NULL, NULL, output, NULL, error);
diff --git a/arch/arm/boot/compressed/piggy.xzkern.S b/arch/arm/boot/compressed/piggy.xzkern.S
new file mode 100644 (file)
index 0000000..5703f30
--- /dev/null
@@ -0,0 +1,6 @@
+       .section .piggydata,#alloc
+       .globl  input_data
+input_data:
+       .incbin "arch/arm/boot/compressed/piggy.xzkern"
+       .globl  input_data_end
+input_data_end:
index 3bb1d7589bd9ec52a864487145cd88a428296253..283fa1d804f4d34208e544f5c3064a72457afc52 100644 (file)
@@ -24,9 +24,6 @@ config ARM_VIC_NR
 config ICST
        bool
 
-config PL330
-       bool
-
 config SA1111
        bool
        select DMABOUNCE if !ARCH_PXA
index 69feafe7286c152f8eed73b998f2fe2e70347de9..215816f1775f5a7a38ed4d5ea5d225aabbad337d 100644 (file)
@@ -5,7 +5,6 @@
 obj-$(CONFIG_ARM_GIC)          += gic.o
 obj-$(CONFIG_ARM_VIC)          += vic.o
 obj-$(CONFIG_ICST)             += icst.o
-obj-$(CONFIG_PL330)            += pl330.o
 obj-$(CONFIG_SA1111)           += sa1111.o
 obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
 obj-$(CONFIG_DMABOUNCE)                += dmabounce.o
index f0783be1735202cafb9dfe715da353f24c0076bb..aa52699841879a36347ec8feafc76b289232739f 100644 (file)
@@ -686,13 +686,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
         * For primary GICs, skip over SGIs.
         * For secondary GICs, skip over PPIs, too.
         */
-       hwirq_base = 32;
-       if (gic_nr == 0) {
-               if ((irq_start & 31) > 0) {
-                       hwirq_base = 16;
-                       if (irq_start != -1)
-                               irq_start = (irq_start & ~31) + 16;
-               }
+       if (gic_nr == 0 && (irq_start & 31) > 0) {
+               hwirq_base = 16;
+               if (irq_start != -1)
+                       irq_start = (irq_start & ~31) + 16;
+       } else {
+               hwirq_base = 32;
        }
 
        /*
diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
deleted file mode 100644 (file)
index ff3ad22..0000000
+++ /dev/null
@@ -1,1960 +0,0 @@
-/* linux/arch/arm/common/pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/hardware/pl330.h>
-
-/* Register and Bit field Definitions */
-#define DS             0x0
-#define DS_ST_STOP     0x0
-#define DS_ST_EXEC     0x1
-#define DS_ST_CMISS    0x2
-#define DS_ST_UPDTPC   0x3
-#define DS_ST_WFE      0x4
-#define DS_ST_ATBRR    0x5
-#define DS_ST_QBUSY    0x6
-#define DS_ST_WFP      0x7
-#define DS_ST_KILL     0x8
-#define DS_ST_CMPLT    0x9
-#define DS_ST_FLTCMP   0xe
-#define DS_ST_FAULT    0xf
-
-#define DPC            0x4
-#define INTEN          0x20
-#define ES             0x24
-#define INTSTATUS      0x28
-#define INTCLR         0x2c
-#define FSM            0x30
-#define FSC            0x34
-#define FTM            0x38
-
-#define _FTC           0x40
-#define FTC(n)         (_FTC + (n)*0x4)
-
-#define _CS            0x100
-#define CS(n)          (_CS + (n)*0x8)
-#define CS_CNS         (1 << 21)
-
-#define _CPC           0x104
-#define CPC(n)         (_CPC + (n)*0x8)
-
-#define _SA            0x400
-#define SA(n)          (_SA + (n)*0x20)
-
-#define _DA            0x404
-#define DA(n)          (_DA + (n)*0x20)
-
-#define _CC            0x408
-#define CC(n)          (_CC + (n)*0x20)
-
-#define CC_SRCINC      (1 << 0)
-#define CC_DSTINC      (1 << 14)
-#define CC_SRCPRI      (1 << 8)
-#define CC_DSTPRI      (1 << 22)
-#define CC_SRCNS       (1 << 9)
-#define CC_DSTNS       (1 << 23)
-#define CC_SRCIA       (1 << 10)
-#define CC_DSTIA       (1 << 24)
-#define CC_SRCBRSTLEN_SHFT     4
-#define CC_DSTBRSTLEN_SHFT     18
-#define CC_SRCBRSTSIZE_SHFT    1
-#define CC_DSTBRSTSIZE_SHFT    15
-#define CC_SRCCCTRL_SHFT       11
-#define CC_SRCCCTRL_MASK       0x7
-#define CC_DSTCCTRL_SHFT       25
-#define CC_DRCCCTRL_MASK       0x7
-#define CC_SWAP_SHFT   28
-
-#define _LC0           0x40c
-#define LC0(n)         (_LC0 + (n)*0x20)
-
-#define _LC1           0x410
-#define LC1(n)         (_LC1 + (n)*0x20)
-
-#define DBGSTATUS      0xd00
-#define DBG_BUSY       (1 << 0)
-
-#define DBGCMD         0xd04
-#define DBGINST0       0xd08
-#define DBGINST1       0xd0c
-
-#define CR0            0xe00
-#define CR1            0xe04
-#define CR2            0xe08
-#define CR3            0xe0c
-#define CR4            0xe10
-#define CRD            0xe14
-
-#define PERIPH_ID      0xfe0
-#define PCELL_ID       0xff0
-
-#define CR0_PERIPH_REQ_SET     (1 << 0)
-#define CR0_BOOT_EN_SET                (1 << 1)
-#define CR0_BOOT_MAN_NS                (1 << 2)
-#define CR0_NUM_CHANS_SHIFT    4
-#define CR0_NUM_CHANS_MASK     0x7
-#define CR0_NUM_PERIPH_SHIFT   12
-#define CR0_NUM_PERIPH_MASK    0x1f
-#define CR0_NUM_EVENTS_SHIFT   17
-#define CR0_NUM_EVENTS_MASK    0x1f
-
-#define CR1_ICACHE_LEN_SHIFT   0
-#define CR1_ICACHE_LEN_MASK    0x7
-#define CR1_NUM_ICACHELINES_SHIFT      4
-#define CR1_NUM_ICACHELINES_MASK       0xf
-
-#define CRD_DATA_WIDTH_SHIFT   0
-#define CRD_DATA_WIDTH_MASK    0x7
-#define CRD_WR_CAP_SHIFT       4
-#define CRD_WR_CAP_MASK                0x7
-#define CRD_WR_Q_DEP_SHIFT     8
-#define CRD_WR_Q_DEP_MASK      0xf
-#define CRD_RD_CAP_SHIFT       12
-#define CRD_RD_CAP_MASK                0x7
-#define CRD_RD_Q_DEP_SHIFT     16
-#define CRD_RD_Q_DEP_MASK      0xf
-#define CRD_DATA_BUFF_SHIFT    20
-#define CRD_DATA_BUFF_MASK     0x3ff
-
-#define        PART            0x330
-#define DESIGNER       0x41
-#define REVISION       0x0
-#define INTEG_CFG      0x0
-#define PERIPH_ID_VAL  ((PART << 0) | (DESIGNER << 12))
-
-#define PCELL_ID_VAL   0xb105f00d
-
-#define PL330_STATE_STOPPED            (1 << 0)
-#define PL330_STATE_EXECUTING          (1 << 1)
-#define PL330_STATE_WFE                        (1 << 2)
-#define PL330_STATE_FAULTING           (1 << 3)
-#define PL330_STATE_COMPLETING         (1 << 4)
-#define PL330_STATE_WFP                        (1 << 5)
-#define PL330_STATE_KILLING            (1 << 6)
-#define PL330_STATE_FAULT_COMPLETING   (1 << 7)
-#define PL330_STATE_CACHEMISS          (1 << 8)
-#define PL330_STATE_UPDTPC             (1 << 9)
-#define PL330_STATE_ATBARRIER          (1 << 10)
-#define PL330_STATE_QUEUEBUSY          (1 << 11)
-#define PL330_STATE_INVALID            (1 << 15)
-
-#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \
-                               | PL330_STATE_WFE | PL330_STATE_FAULTING)
-
-#define CMD_DMAADDH    0x54
-#define CMD_DMAEND     0x00
-#define CMD_DMAFLUSHP  0x35
-#define CMD_DMAGO      0xa0
-#define CMD_DMALD      0x04
-#define CMD_DMALDP     0x25
-#define CMD_DMALP      0x20
-#define CMD_DMALPEND   0x28
-#define CMD_DMAKILL    0x01
-#define CMD_DMAMOV     0xbc
-#define CMD_DMANOP     0x18
-#define CMD_DMARMB     0x12
-#define CMD_DMASEV     0x34
-#define CMD_DMAST      0x08
-#define CMD_DMASTP     0x29
-#define CMD_DMASTZ     0x0c
-#define CMD_DMAWFE     0x36
-#define CMD_DMAWFP     0x30
-#define CMD_DMAWMB     0x13
-
-#define SZ_DMAADDH     3
-#define SZ_DMAEND      1
-#define SZ_DMAFLUSHP   2
-#define SZ_DMALD       1
-#define SZ_DMALDP      2
-#define SZ_DMALP       2
-#define SZ_DMALPEND    2
-#define SZ_DMAKILL     1
-#define SZ_DMAMOV      6
-#define SZ_DMANOP      1
-#define SZ_DMARMB      1
-#define SZ_DMASEV      2
-#define SZ_DMAST       1
-#define SZ_DMASTP      2
-#define SZ_DMASTZ      1
-#define SZ_DMAWFE      2
-#define SZ_DMAWFP      2
-#define SZ_DMAWMB      1
-#define SZ_DMAGO       6
-
-#define BRST_LEN(ccr)  ((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1)
-#define BRST_SIZE(ccr) (1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7))
-
-#define BYTE_TO_BURST(b, ccr)  ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr))
-#define BURST_TO_BYTE(c, ccr)  ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr))
-
-/*
- * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req
- * at 1byte/burst for P<->M and M<->M respectively.
- * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req
- * should be enough for P<->M and M<->M respectively.
- */
-#define MCODE_BUFF_PER_REQ     256
-
-/* If the _pl330_req is available to the client */
-#define IS_FREE(req)   (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
-
-/* Use this _only_ to wait on transient states */
-#define UNTIL(t, s)    while (!(_state(t) & (s))) cpu_relax();
-
-#ifdef PL330_DEBUG_MCGEN
-static unsigned cmd_line;
-#define PL330_DBGCMD_DUMP(off, x...)   do { \
-                                               printk("%x:", cmd_line); \
-                                               printk(x); \
-                                               cmd_line += off; \
-                                       } while (0)
-#define PL330_DBGMC_START(addr)                (cmd_line = addr)
-#else
-#define PL330_DBGCMD_DUMP(off, x...)   do {} while (0)
-#define PL330_DBGMC_START(addr)                do {} while (0)
-#endif
-
-struct _xfer_spec {
-       u32 ccr;
-       struct pl330_req *r;
-       struct pl330_xfer *x;
-};
-
-enum dmamov_dst {
-       SAR = 0,
-       CCR,
-       DAR,
-};
-
-enum pl330_dst {
-       SRC = 0,
-       DST,
-};
-
-enum pl330_cond {
-       SINGLE,
-       BURST,
-       ALWAYS,
-};
-
-struct _pl330_req {
-       u32 mc_bus;
-       void *mc_cpu;
-       /* Number of bytes taken to setup MC for the req */
-       u32 mc_len;
-       struct pl330_req *r;
-       /* Hook to attach to DMAC's list of reqs with due callback */
-       struct list_head rqd;
-};
-
-/* ToBeDone for tasklet */
-struct _pl330_tbd {
-       bool reset_dmac;
-       bool reset_mngr;
-       u8 reset_chan;
-};
-
-/* A DMAC Thread */
-struct pl330_thread {
-       u8 id;
-       int ev;
-       /* If the channel is not yet acquired by any client */
-       bool free;
-       /* Parent DMAC */
-       struct pl330_dmac *dmac;
-       /* Only two at a time */
-       struct _pl330_req req[2];
-       /* Index of the last enqueued request */
-       unsigned lstenq;
-       /* Index of the last submitted request or -1 if the DMA is stopped */
-       int req_running;
-};
-
-enum pl330_dmac_state {
-       UNINIT,
-       INIT,
-       DYING,
-};
-
-/* A DMAC */
-struct pl330_dmac {
-       spinlock_t              lock;
-       /* Holds list of reqs with due callbacks */
-       struct list_head        req_done;
-       /* Pointer to platform specific stuff */
-       struct pl330_info       *pinfo;
-       /* Maximum possible events/irqs */
-       int                     events[32];
-       /* BUS address of MicroCode buffer */
-       u32                     mcode_bus;
-       /* CPU address of MicroCode buffer */
-       void                    *mcode_cpu;
-       /* List of all Channel threads */
-       struct pl330_thread     *channels;
-       /* Pointer to the MANAGER thread */
-       struct pl330_thread     *manager;
-       /* To handle bad news in interrupt */
-       struct tasklet_struct   tasks;
-       struct _pl330_tbd       dmac_tbd;
-       /* State of DMAC operation */
-       enum pl330_dmac_state   state;
-};
-
-static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
-{
-       if (r && r->xfer_cb)
-               r->xfer_cb(r->token, err);
-}
-
-static inline bool _queue_empty(struct pl330_thread *thrd)
-{
-       return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
-               ? true : false;
-}
-
-static inline bool _queue_full(struct pl330_thread *thrd)
-{
-       return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
-               ? false : true;
-}
-
-static inline bool is_manager(struct pl330_thread *thrd)
-{
-       struct pl330_dmac *pl330 = thrd->dmac;
-
-       /* MANAGER is indexed at the end */
-       if (thrd->id == pl330->pinfo->pcfg.num_chan)
-               return true;
-       else
-               return false;
-}
-
-/* If manager of the thread is in Non-Secure mode */
-static inline bool _manager_ns(struct pl330_thread *thrd)
-{
-       struct pl330_dmac *pl330 = thrd->dmac;
-
-       return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
-}
-
-static inline u32 get_id(struct pl330_info *pi, u32 off)
-{
-       void __iomem *regs = pi->base;
-       u32 id = 0;
-
-       id |= (readb(regs + off + 0x0) << 0);
-       id |= (readb(regs + off + 0x4) << 8);
-       id |= (readb(regs + off + 0x8) << 16);
-       id |= (readb(regs + off + 0xc) << 24);
-
-       return id;
-}
-
-static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
-               enum pl330_dst da, u16 val)
-{
-       if (dry_run)
-               return SZ_DMAADDH;
-
-       buf[0] = CMD_DMAADDH;
-       buf[0] |= (da << 1);
-       *((u16 *)&buf[1]) = val;
-
-       PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
-               da == 1 ? "DA" : "SA", val);
-
-       return SZ_DMAADDH;
-}
-
-static inline u32 _emit_END(unsigned dry_run, u8 buf[])
-{
-       if (dry_run)
-               return SZ_DMAEND;
-
-       buf[0] = CMD_DMAEND;
-
-       PL330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n");
-
-       return SZ_DMAEND;
-}
-
-static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri)
-{
-       if (dry_run)
-               return SZ_DMAFLUSHP;
-
-       buf[0] = CMD_DMAFLUSHP;
-
-       peri &= 0x1f;
-       peri <<= 3;
-       buf[1] = peri;
-
-       PL330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3);
-
-       return SZ_DMAFLUSHP;
-}
-
-static inline u32 _emit_LD(unsigned dry_run, u8 buf[], enum pl330_cond cond)
-{
-       if (dry_run)
-               return SZ_DMALD;
-
-       buf[0] = CMD_DMALD;
-
-       if (cond == SINGLE)
-               buf[0] |= (0 << 1) | (1 << 0);
-       else if (cond == BURST)
-               buf[0] |= (1 << 1) | (1 << 0);
-
-       PL330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n",
-               cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
-
-       return SZ_DMALD;
-}
-
-static inline u32 _emit_LDP(unsigned dry_run, u8 buf[],
-               enum pl330_cond cond, u8 peri)
-{
-       if (dry_run)
-               return SZ_DMALDP;
-
-       buf[0] = CMD_DMALDP;
-
-       if (cond == BURST)
-               buf[0] |= (1 << 1);
-
-       peri &= 0x1f;
-       peri <<= 3;
-       buf[1] = peri;
-
-       PL330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n",
-               cond == SINGLE ? 'S' : 'B', peri >> 3);
-
-       return SZ_DMALDP;
-}
-
-static inline u32 _emit_LP(unsigned dry_run, u8 buf[],
-               unsigned loop, u8 cnt)
-{
-       if (dry_run)
-               return SZ_DMALP;
-
-       buf[0] = CMD_DMALP;
-
-       if (loop)
-               buf[0] |= (1 << 1);
-
-       cnt--; /* DMAC increments by 1 internally */
-       buf[1] = cnt;
-
-       PL330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt);
-
-       return SZ_DMALP;
-}
-
-struct _arg_LPEND {
-       enum pl330_cond cond;
-       bool forever;
-       unsigned loop;
-       u8 bjump;
-};
-
-static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[],
-               const struct _arg_LPEND *arg)
-{
-       enum pl330_cond cond = arg->cond;
-       bool forever = arg->forever;
-       unsigned loop = arg->loop;
-       u8 bjump = arg->bjump;
-
-       if (dry_run)
-               return SZ_DMALPEND;
-
-       buf[0] = CMD_DMALPEND;
-
-       if (loop)
-               buf[0] |= (1 << 2);
-
-       if (!forever)
-               buf[0] |= (1 << 4);
-
-       if (cond == SINGLE)
-               buf[0] |= (0 << 1) | (1 << 0);
-       else if (cond == BURST)
-               buf[0] |= (1 << 1) | (1 << 0);
-
-       buf[1] = bjump;
-
-       PL330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n",
-                       forever ? "FE" : "END",
-                       cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'),
-                       loop ? '1' : '0',
-                       bjump);
-
-       return SZ_DMALPEND;
-}
-
-static inline u32 _emit_KILL(unsigned dry_run, u8 buf[])
-{
-       if (dry_run)
-               return SZ_DMAKILL;
-
-       buf[0] = CMD_DMAKILL;
-
-       return SZ_DMAKILL;
-}
-
-static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
-               enum dmamov_dst dst, u32 val)
-{
-       if (dry_run)
-               return SZ_DMAMOV;
-
-       buf[0] = CMD_DMAMOV;
-       buf[1] = dst;
-       *((u32 *)&buf[2]) = val;
-
-       PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
-               dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
-
-       return SZ_DMAMOV;
-}
-
-static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
-{
-       if (dry_run)
-               return SZ_DMANOP;
-
-       buf[0] = CMD_DMANOP;
-
-       PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
-
-       return SZ_DMANOP;
-}
-
-static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
-{
-       if (dry_run)
-               return SZ_DMARMB;
-
-       buf[0] = CMD_DMARMB;
-
-       PL330_DBGCMD_DUMP(SZ_DMARMB, "\tDMARMB\n");
-
-       return SZ_DMARMB;
-}
-
-static inline u32 _emit_SEV(unsigned dry_run, u8 buf[], u8 ev)
-{
-       if (dry_run)
-               return SZ_DMASEV;
-
-       buf[0] = CMD_DMASEV;
-
-       ev &= 0x1f;
-       ev <<= 3;
-       buf[1] = ev;
-
-       PL330_DBGCMD_DUMP(SZ_DMASEV, "\tDMASEV %u\n", ev >> 3);
-
-       return SZ_DMASEV;
-}
-
-static inline u32 _emit_ST(unsigned dry_run, u8 buf[], enum pl330_cond cond)
-{
-       if (dry_run)
-               return SZ_DMAST;
-
-       buf[0] = CMD_DMAST;
-
-       if (cond == SINGLE)
-               buf[0] |= (0 << 1) | (1 << 0);
-       else if (cond == BURST)
-               buf[0] |= (1 << 1) | (1 << 0);
-
-       PL330_DBGCMD_DUMP(SZ_DMAST, "\tDMAST%c\n",
-               cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
-
-       return SZ_DMAST;
-}
-
-static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
-               enum pl330_cond cond, u8 peri)
-{
-       if (dry_run)
-               return SZ_DMASTP;
-
-       buf[0] = CMD_DMASTP;
-
-       if (cond == BURST)
-               buf[0] |= (1 << 1);
-
-       peri &= 0x1f;
-       peri <<= 3;
-       buf[1] = peri;
-
-       PL330_DBGCMD_DUMP(SZ_DMASTP, "\tDMASTP%c %u\n",
-               cond == SINGLE ? 'S' : 'B', peri >> 3);
-
-       return SZ_DMASTP;
-}
-
-static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
-{
-       if (dry_run)
-               return SZ_DMASTZ;
-
-       buf[0] = CMD_DMASTZ;
-
-       PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
-
-       return SZ_DMASTZ;
-}
-
-static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
-               unsigned invalidate)
-{
-       if (dry_run)
-               return SZ_DMAWFE;
-
-       buf[0] = CMD_DMAWFE;
-
-       ev &= 0x1f;
-       ev <<= 3;
-       buf[1] = ev;
-
-       if (invalidate)
-               buf[1] |= (1 << 1);
-
-       PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
-               ev >> 3, invalidate ? ", I" : "");
-
-       return SZ_DMAWFE;
-}
-
-static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
-               enum pl330_cond cond, u8 peri)
-{
-       if (dry_run)
-               return SZ_DMAWFP;
-
-       buf[0] = CMD_DMAWFP;
-
-       if (cond == SINGLE)
-               buf[0] |= (0 << 1) | (0 << 0);
-       else if (cond == BURST)
-               buf[0] |= (1 << 1) | (0 << 0);
-       else
-               buf[0] |= (0 << 1) | (1 << 0);
-
-       peri &= 0x1f;
-       peri <<= 3;
-       buf[1] = peri;
-
-       PL330_DBGCMD_DUMP(SZ_DMAWFP, "\tDMAWFP%c %u\n",
-               cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'P'), peri >> 3);
-
-       return SZ_DMAWFP;
-}
-
-static inline u32 _emit_WMB(unsigned dry_run, u8 buf[])
-{
-       if (dry_run)
-               return SZ_DMAWMB;
-
-       buf[0] = CMD_DMAWMB;
-
-       PL330_DBGCMD_DUMP(SZ_DMAWMB, "\tDMAWMB\n");
-
-       return SZ_DMAWMB;
-}
-
-struct _arg_GO {
-       u8 chan;
-       u32 addr;
-       unsigned ns;
-};
-
-static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
-               const struct _arg_GO *arg)
-{
-       u8 chan = arg->chan;
-       u32 addr = arg->addr;
-       unsigned ns = arg->ns;
-
-       if (dry_run)
-               return SZ_DMAGO;
-
-       buf[0] = CMD_DMAGO;
-       buf[0] |= (ns << 1);
-
-       buf[1] = chan & 0x7;
-
-       *((u32 *)&buf[2]) = addr;
-
-       return SZ_DMAGO;
-}
-
-#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-
-/* Returns Time-Out */
-static bool _until_dmac_idle(struct pl330_thread *thrd)
-{
-       void __iomem *regs = thrd->dmac->pinfo->base;
-       unsigned long loops = msecs_to_loops(5);
-
-       do {
-               /* Until Manager is Idle */
-               if (!(readl(regs + DBGSTATUS) & DBG_BUSY))
-                       break;
-
-               cpu_relax();
-       } while (--loops);
-
-       if (!loops)
-               return true;
-
-       return false;
-}
-
-static inline void _execute_DBGINSN(struct pl330_thread *thrd,
-               u8 insn[], bool as_manager)
-{
-       void __iomem *regs = thrd->dmac->pinfo->base;
-       u32 val;
-
-       val = (insn[0] << 16) | (insn[1] << 24);
-       if (!as_manager) {
-               val |= (1 << 0);
-               val |= (thrd->id << 8); /* Channel Number */
-       }
-       writel(val, regs + DBGINST0);
-
-       val = *((u32 *)&insn[2]);
-       writel(val, regs + DBGINST1);
-
-       /* If timed out due to halted state-machine */
-       if (_until_dmac_idle(thrd)) {
-               dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n");
-               return;
-       }
-
-       /* Get going */
-       writel(0, regs + DBGCMD);
-}
-
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-static void mark_free(struct pl330_thread *thrd, int idx)
-{
-       struct _pl330_req *req = &thrd->req[idx];
-
-       _emit_END(0, req->mc_cpu);
-       req->mc_len = 0;
-
-       thrd->req_running = -1;
-}
-
-static inline u32 _state(struct pl330_thread *thrd)
-{
-       void __iomem *regs = thrd->dmac->pinfo->base;
-       u32 val;
-
-       if (is_manager(thrd))
-               val = readl(regs + DS) & 0xf;
-       else
-               val = readl(regs + CS(thrd->id)) & 0xf;
-
-       switch (val) {
-       case DS_ST_STOP:
-               return PL330_STATE_STOPPED;
-       case DS_ST_EXEC:
-               return PL330_STATE_EXECUTING;
-       case DS_ST_CMISS:
-               return PL330_STATE_CACHEMISS;
-       case DS_ST_UPDTPC:
-               return PL330_STATE_UPDTPC;
-       case DS_ST_WFE:
-               return PL330_STATE_WFE;
-       case DS_ST_FAULT:
-               return PL330_STATE_FAULTING;
-       case DS_ST_ATBRR:
-               if (is_manager(thrd))
-                       return PL330_STATE_INVALID;
-               else
-                       return PL330_STATE_ATBARRIER;
-       case DS_ST_QBUSY:
-               if (is_manager(thrd))
-                       return PL330_STATE_INVALID;
-               else
-                       return PL330_STATE_QUEUEBUSY;
-       case DS_ST_WFP:
-               if (is_manager(thrd))
-                       return PL330_STATE_INVALID;
-               else
-                       return PL330_STATE_WFP;
-       case DS_ST_KILL:
-               if (is_manager(thrd))
-                       return PL330_STATE_INVALID;
-               else
-                       return PL330_STATE_KILLING;
-       case DS_ST_CMPLT:
-               if (is_manager(thrd))
-                       return PL330_STATE_INVALID;
-               else
-                       return PL330_STATE_COMPLETING;
-       case DS_ST_FLTCMP:
-               if (is_manager(thrd))
-                       return PL330_STATE_INVALID;
-               else
-                       return PL330_STATE_FAULT_COMPLETING;
-       default:
-               return PL330_STATE_INVALID;
-       }
-}
-
-static void _stop(struct pl330_thread *thrd)
-{
-       void __iomem *regs = thrd->dmac->pinfo->base;
-       u8 insn[6] = {0, 0, 0, 0, 0, 0};
-
-       if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
-               UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
-
-       /* Return if nothing needs to be done */
-       if (_state(thrd) == PL330_STATE_COMPLETING
-                 || _state(thrd) == PL330_STATE_KILLING
-                 || _state(thrd) == PL330_STATE_STOPPED)
-               return;
-
-       _emit_KILL(0, insn);
-
-       /* Stop generating interrupts for SEV */
-       writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
-
-       _execute_DBGINSN(thrd, insn, is_manager(thrd));
-}
-
-/* Start doing req 'idx' of thread 'thrd' */
-static bool _trigger(struct pl330_thread *thrd)
-{
-       void __iomem *regs = thrd->dmac->pinfo->base;
-       struct _pl330_req *req;
-       struct pl330_req *r;
-       struct _arg_GO go;
-       unsigned ns;
-       u8 insn[6] = {0, 0, 0, 0, 0, 0};
-       int idx;
-
-       /* Return if already ACTIVE */
-       if (_state(thrd) != PL330_STATE_STOPPED)
-               return true;
-
-       idx = 1 - thrd->lstenq;
-       if (!IS_FREE(&thrd->req[idx]))
-               req = &thrd->req[idx];
-       else {
-               idx = thrd->lstenq;
-               if (!IS_FREE(&thrd->req[idx]))
-                       req = &thrd->req[idx];
-               else
-                       req = NULL;
-       }
-
-       /* Return if no request */
-       if (!req || !req->r)
-               return true;
-
-       r = req->r;
-
-       if (r->cfg)
-               ns = r->cfg->nonsecure ? 1 : 0;
-       else if (readl(regs + CS(thrd->id)) & CS_CNS)
-               ns = 1;
-       else
-               ns = 0;
-
-       /* See 'Abort Sources' point-4 at Page 2-25 */
-       if (_manager_ns(thrd) && !ns)
-               dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n",
-                       __func__, __LINE__);
-
-       go.chan = thrd->id;
-       go.addr = req->mc_bus;
-       go.ns = ns;
-       _emit_GO(0, insn, &go);
-
-       /* Set to generate interrupts for SEV */
-       writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN);
-
-       /* Only manager can execute GO */
-       _execute_DBGINSN(thrd, insn, true);
-
-       thrd->req_running = idx;
-
-       return true;
-}
-
-static bool _start(struct pl330_thread *thrd)
-{
-       switch (_state(thrd)) {
-       case PL330_STATE_FAULT_COMPLETING:
-               UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
-
-               if (_state(thrd) == PL330_STATE_KILLING)
-                       UNTIL(thrd, PL330_STATE_STOPPED)
-
-       case PL330_STATE_FAULTING:
-               _stop(thrd);
-
-       case PL330_STATE_KILLING:
-       case PL330_STATE_COMPLETING:
-               UNTIL(thrd, PL330_STATE_STOPPED)
-
-       case PL330_STATE_STOPPED:
-               return _trigger(thrd);
-
-       case PL330_STATE_WFP:
-       case PL330_STATE_QUEUEBUSY:
-       case PL330_STATE_ATBARRIER:
-       case PL330_STATE_UPDTPC:
-       case PL330_STATE_CACHEMISS:
-       case PL330_STATE_EXECUTING:
-               return true;
-
-       case PL330_STATE_WFE: /* For RESUME, nothing yet */
-       default:
-               return false;
-       }
-}
-
-static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
-               const struct _xfer_spec *pxs, int cyc)
-{
-       int off = 0;
-
-       while (cyc--) {
-               off += _emit_LD(dry_run, &buf[off], ALWAYS);
-               off += _emit_RMB(dry_run, &buf[off]);
-               off += _emit_ST(dry_run, &buf[off], ALWAYS);
-               off += _emit_WMB(dry_run, &buf[off]);
-       }
-
-       return off;
-}
-
-static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
-               const struct _xfer_spec *pxs, int cyc)
-{
-       int off = 0;
-
-       while (cyc--) {
-               off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-               off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-               off += _emit_ST(dry_run, &buf[off], ALWAYS);
-               off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
-       }
-
-       return off;
-}
-
-static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
-               const struct _xfer_spec *pxs, int cyc)
-{
-       int off = 0;
-
-       while (cyc--) {
-               off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-               off += _emit_LD(dry_run, &buf[off], ALWAYS);
-               off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-               off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
-       }
-
-       return off;
-}
-
-static int _bursts(unsigned dry_run, u8 buf[],
-               const struct _xfer_spec *pxs, int cyc)
-{
-       int off = 0;
-
-       switch (pxs->r->rqtype) {
-       case MEMTODEV:
-               off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
-               break;
-       case DEVTOMEM:
-               off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
-               break;
-       case MEMTOMEM:
-               off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
-               break;
-       default:
-               off += 0x40000000; /* Scare off the Client */
-               break;
-       }
-
-       return off;
-}
-
-/* Returns bytes consumed and updates bursts */
-static inline int _loop(unsigned dry_run, u8 buf[],
-               unsigned long *bursts, const struct _xfer_spec *pxs)
-{
-       int cyc, cycmax, szlp, szlpend, szbrst, off;
-       unsigned lcnt0, lcnt1, ljmp0, ljmp1;
-       struct _arg_LPEND lpend;
-
-       /* Max iterations possible in DMALP is 256 */
-       if (*bursts >= 256*256) {
-               lcnt1 = 256;
-               lcnt0 = 256;
-               cyc = *bursts / lcnt1 / lcnt0;
-       } else if (*bursts > 256) {
-               lcnt1 = 256;
-               lcnt0 = *bursts / lcnt1;
-               cyc = 1;
-       } else {
-               lcnt1 = *bursts;
-               lcnt0 = 0;
-               cyc = 1;
-       }
-
-       szlp = _emit_LP(1, buf, 0, 0);
-       szbrst = _bursts(1, buf, pxs, 1);
-
-       lpend.cond = ALWAYS;
-       lpend.forever = false;
-       lpend.loop = 0;
-       lpend.bjump = 0;
-       szlpend = _emit_LPEND(1, buf, &lpend);
-
-       if (lcnt0) {
-               szlp *= 2;
-               szlpend *= 2;
-       }
-
-       /*
-        * Max bursts that we can unroll due to limit on the
-        * size of backward jump that can be encoded in DMALPEND
-        * which is 8-bits and hence 255
-        */
-       cycmax = (255 - (szlp + szlpend)) / szbrst;
-
-       cyc = (cycmax < cyc) ? cycmax : cyc;
-
-       off = 0;
-
-       if (lcnt0) {
-               off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
-               ljmp0 = off;
-       }
-
-       off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
-       ljmp1 = off;
-
-       off += _bursts(dry_run, &buf[off], pxs, cyc);
-
-       lpend.cond = ALWAYS;
-       lpend.forever = false;
-       lpend.loop = 1;
-       lpend.bjump = off - ljmp1;
-       off += _emit_LPEND(dry_run, &buf[off], &lpend);
-
-       if (lcnt0) {
-               lpend.cond = ALWAYS;
-               lpend.forever = false;
-               lpend.loop = 0;
-               lpend.bjump = off - ljmp0;
-               off += _emit_LPEND(dry_run, &buf[off], &lpend);
-       }
-
-       *bursts = lcnt1 * cyc;
-       if (lcnt0)
-               *bursts *= lcnt0;
-
-       return off;
-}
-
-static inline int _setup_loops(unsigned dry_run, u8 buf[],
-               const struct _xfer_spec *pxs)
-{
-       struct pl330_xfer *x = pxs->x;
-       u32 ccr = pxs->ccr;
-       unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
-       int off = 0;
-
-       while (bursts) {
-               c = bursts;
-               off += _loop(dry_run, &buf[off], &c, pxs);
-               bursts -= c;
-       }
-
-       return off;
-}
-
-static inline int _setup_xfer(unsigned dry_run, u8 buf[],
-               const struct _xfer_spec *pxs)
-{
-       struct pl330_xfer *x = pxs->x;
-       int off = 0;
-
-       /* DMAMOV SAR, x->src_addr */
-       off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
-       /* DMAMOV DAR, x->dst_addr */
-       off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
-
-       /* Setup Loop(s) */
-       off += _setup_loops(dry_run, &buf[off], pxs);
-
-       return off;
-}
-
-/*
- * A req is a sequence of one or more xfer units.
- * Returns the number of bytes taken to setup the MC for the req.
- */
-static int _setup_req(unsigned dry_run, struct pl330_thread *thrd,
-               unsigned index, struct _xfer_spec *pxs)
-{
-       struct _pl330_req *req = &thrd->req[index];
-       struct pl330_xfer *x;
-       u8 *buf = req->mc_cpu;
-       int off = 0;
-
-       PL330_DBGMC_START(req->mc_bus);
-
-       /* DMAMOV CCR, ccr */
-       off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
-
-       x = pxs->r->x;
-       do {
-               /* Error if xfer length is not aligned at burst size */
-               if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
-                       return -EINVAL;
-
-               pxs->x = x;
-               off += _setup_xfer(dry_run, &buf[off], pxs);
-
-               x = x->next;
-       } while (x);
-
-       /* DMASEV peripheral/event */
-       off += _emit_SEV(dry_run, &buf[off], thrd->ev);
-       /* DMAEND */
-       off += _emit_END(dry_run, &buf[off]);
-
-       return off;
-}
-
-static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
-{
-       u32 ccr = 0;
-
-       if (rqc->src_inc)
-               ccr |= CC_SRCINC;
-
-       if (rqc->dst_inc)
-               ccr |= CC_DSTINC;
-
-       /* We set same protection levels for Src and DST for now */
-       if (rqc->privileged)
-               ccr |= CC_SRCPRI | CC_DSTPRI;
-       if (rqc->nonsecure)
-               ccr |= CC_SRCNS | CC_DSTNS;
-       if (rqc->insnaccess)
-               ccr |= CC_SRCIA | CC_DSTIA;
-
-       ccr |= (((rqc->brst_len - 1) & 0xf) << CC_SRCBRSTLEN_SHFT);
-       ccr |= (((rqc->brst_len - 1) & 0xf) << CC_DSTBRSTLEN_SHFT);
-
-       ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
-       ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
-
-       ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
-       ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
-
-       ccr |= (rqc->swap << CC_SWAP_SHFT);
-
-       return ccr;
-}
-
-static inline bool _is_valid(u32 ccr)
-{
-       enum pl330_dstcachectrl dcctl;
-       enum pl330_srccachectrl scctl;
-
-       dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK;
-       scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK;
-
-       if (dcctl == DINVALID1 || dcctl == DINVALID2
-                       || scctl == SINVALID1 || scctl == SINVALID2)
-               return false;
-       else
-               return true;
-}
-
-/*
- * Submit a list of xfers after which the client wants notification.
- * Client is not notified after each xfer unit, just once after all
- * xfer units are done or some error occurs.
- */
-int pl330_submit_req(void *ch_id, struct pl330_req *r)
-{
-       struct pl330_thread *thrd = ch_id;
-       struct pl330_dmac *pl330;
-       struct pl330_info *pi;
-       struct _xfer_spec xs;
-       unsigned long flags;
-       void __iomem *regs;
-       unsigned idx;
-       u32 ccr;
-       int ret = 0;
-
-       /* No Req or Unacquired Channel or DMAC */
-       if (!r || !thrd || thrd->free)
-               return -EINVAL;
-
-       pl330 = thrd->dmac;
-       pi = pl330->pinfo;
-       regs = pi->base;
-
-       if (pl330->state == DYING
-               || pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
-               dev_info(thrd->dmac->pinfo->dev, "%s:%d\n",
-                       __func__, __LINE__);
-               return -EAGAIN;
-       }
-
-       /* If request for non-existing peripheral */
-       if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) {
-               dev_info(thrd->dmac->pinfo->dev,
-                               "%s:%d Invalid peripheral(%u)!\n",
-                               __func__, __LINE__, r->peri);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&pl330->lock, flags);
-
-       if (_queue_full(thrd)) {
-               ret = -EAGAIN;
-               goto xfer_exit;
-       }
-
-       /* Prefer Secure Channel */
-       if (!_manager_ns(thrd))
-               r->cfg->nonsecure = 0;
-       else
-               r->cfg->nonsecure = 1;
-
-       /* Use last settings, if not provided */
-       if (r->cfg)
-               ccr = _prepare_ccr(r->cfg);
-       else
-               ccr = readl(regs + CC(thrd->id));
-
-       /* If this req doesn't have valid xfer settings */
-       if (!_is_valid(ccr)) {
-               ret = -EINVAL;
-               dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n",
-                       __func__, __LINE__, ccr);
-               goto xfer_exit;
-       }
-
-       idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
-
-       xs.ccr = ccr;
-       xs.r = r;
-
-       /* First dry run to check if req is acceptable */
-       ret = _setup_req(1, thrd, idx, &xs);
-       if (ret < 0)
-               goto xfer_exit;
-
-       if (ret > pi->mcbufsz / 2) {
-               dev_info(thrd->dmac->pinfo->dev,
-                       "%s:%d Trying increasing mcbufsz\n",
-                               __func__, __LINE__);
-               ret = -ENOMEM;
-               goto xfer_exit;
-       }
-
-       /* Hook the request */
-       thrd->lstenq = idx;
-       thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs);
-       thrd->req[idx].r = r;
-
-       ret = 0;
-
-xfer_exit:
-       spin_unlock_irqrestore(&pl330->lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(pl330_submit_req);
-
-static void pl330_dotask(unsigned long data)
-{
-       struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
-       struct pl330_info *pi = pl330->pinfo;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&pl330->lock, flags);
-
-       /* The DMAC itself gone nuts */
-       if (pl330->dmac_tbd.reset_dmac) {
-               pl330->state = DYING;
-               /* Reset the manager too */
-               pl330->dmac_tbd.reset_mngr = true;
-               /* Clear the reset flag */
-               pl330->dmac_tbd.reset_dmac = false;
-       }
-
-       if (pl330->dmac_tbd.reset_mngr) {
-               _stop(pl330->manager);
-               /* Reset all channels */
-               pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1;
-               /* Clear the reset flag */
-               pl330->dmac_tbd.reset_mngr = false;
-       }
-
-       for (i = 0; i < pi->pcfg.num_chan; i++) {
-
-               if (pl330->dmac_tbd.reset_chan & (1 << i)) {
-                       struct pl330_thread *thrd = &pl330->channels[i];
-                       void __iomem *regs = pi->base;
-                       enum pl330_op_err err;
-
-                       _stop(thrd);
-
-                       if (readl(regs + FSC) & (1 << thrd->id))
-                               err = PL330_ERR_FAIL;
-                       else
-                               err = PL330_ERR_ABORT;
-
-                       spin_unlock_irqrestore(&pl330->lock, flags);
-
-                       _callback(thrd->req[1 - thrd->lstenq].r, err);
-                       _callback(thrd->req[thrd->lstenq].r, err);
-
-                       spin_lock_irqsave(&pl330->lock, flags);
-
-                       thrd->req[0].r = NULL;
-                       thrd->req[1].r = NULL;
-                       mark_free(thrd, 0);
-                       mark_free(thrd, 1);
-
-                       /* Clear the reset flag */
-                       pl330->dmac_tbd.reset_chan &= ~(1 << i);
-               }
-       }
-
-       spin_unlock_irqrestore(&pl330->lock, flags);
-
-       return;
-}
-
-/* Returns 1 if state was updated, 0 otherwise */
-int pl330_update(const struct pl330_info *pi)
-{
-       struct _pl330_req *rqdone;
-       struct pl330_dmac *pl330;
-       unsigned long flags;
-       void __iomem *regs;
-       u32 val;
-       int id, ev, ret = 0;
-
-       if (!pi || !pi->pl330_data)
-               return 0;
-
-       regs = pi->base;
-       pl330 = pi->pl330_data;
-
-       spin_lock_irqsave(&pl330->lock, flags);
-
-       val = readl(regs + FSM) & 0x1;
-       if (val)
-               pl330->dmac_tbd.reset_mngr = true;
-       else
-               pl330->dmac_tbd.reset_mngr = false;
-
-       val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
-       pl330->dmac_tbd.reset_chan |= val;
-       if (val) {
-               int i = 0;
-               while (i < pi->pcfg.num_chan) {
-                       if (val & (1 << i)) {
-                               dev_info(pi->dev,
-                                       "Reset Channel-%d\t CS-%x FTC-%x\n",
-                                               i, readl(regs + CS(i)),
-                                               readl(regs + FTC(i)));
-                               _stop(&pl330->channels[i]);
-                       }
-                       i++;
-               }
-       }
-
-       /* Check which event happened i.e, thread notified */
-       val = readl(regs + ES);
-       if (pi->pcfg.num_events < 32
-                       && val & ~((1 << pi->pcfg.num_events) - 1)) {
-               pl330->dmac_tbd.reset_dmac = true;
-               dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__);
-               ret = 1;
-               goto updt_exit;
-       }
-
-       for (ev = 0; ev < pi->pcfg.num_events; ev++) {
-               if (val & (1 << ev)) { /* Event occurred */
-                       struct pl330_thread *thrd;
-                       u32 inten = readl(regs + INTEN);
-                       int active;
-
-                       /* Clear the event */
-                       if (inten & (1 << ev))
-                               writel(1 << ev, regs + INTCLR);
-
-                       ret = 1;
-
-                       id = pl330->events[ev];
-
-                       thrd = &pl330->channels[id];
-
-                       active = thrd->req_running;
-                       if (active == -1) /* Aborted */
-                               continue;
-
-                       rqdone = &thrd->req[active];
-                       mark_free(thrd, active);
-
-                       /* Get going again ASAP */
-                       _start(thrd);
-
-                       /* For now, just make a list of callbacks to be done */
-                       list_add_tail(&rqdone->rqd, &pl330->req_done);
-               }
-       }
-
-       /* Now that we are in no hurry, do the callbacks */
-       while (!list_empty(&pl330->req_done)) {
-               struct pl330_req *r;
-
-               rqdone = container_of(pl330->req_done.next,
-                                       struct _pl330_req, rqd);
-
-               list_del_init(&rqdone->rqd);
-
-               /* Detach the req */
-               r = rqdone->r;
-               rqdone->r = NULL;
-
-               spin_unlock_irqrestore(&pl330->lock, flags);
-               _callback(r, PL330_ERR_NONE);
-               spin_lock_irqsave(&pl330->lock, flags);
-       }
-
-updt_exit:
-       spin_unlock_irqrestore(&pl330->lock, flags);
-
-       if (pl330->dmac_tbd.reset_dmac
-                       || pl330->dmac_tbd.reset_mngr
-                       || pl330->dmac_tbd.reset_chan) {
-               ret = 1;
-               tasklet_schedule(&pl330->tasks);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(pl330_update);
-
-int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
-{
-       struct pl330_thread *thrd = ch_id;
-       struct pl330_dmac *pl330;
-       unsigned long flags;
-       int ret = 0, active;
-
-       if (!thrd || thrd->free || thrd->dmac->state == DYING)
-               return -EINVAL;
-
-       pl330 = thrd->dmac;
-       active = thrd->req_running;
-
-       spin_lock_irqsave(&pl330->lock, flags);
-
-       switch (op) {
-       case PL330_OP_FLUSH:
-               /* Make sure the channel is stopped */
-               _stop(thrd);
-
-               thrd->req[0].r = NULL;
-               thrd->req[1].r = NULL;
-               mark_free(thrd, 0);
-               mark_free(thrd, 1);
-               break;
-
-       case PL330_OP_ABORT:
-               /* Make sure the channel is stopped */
-               _stop(thrd);
-
-               /* ABORT is only for the active req */
-               if (active == -1)
-                       break;
-
-               thrd->req[active].r = NULL;
-               mark_free(thrd, active);
-
-               /* Start the next */
-       case PL330_OP_START:
-               if ((active == -1) && !_start(thrd))
-                       ret = -EIO;
-               break;
-
-       default:
-               ret = -EINVAL;
-       }
-
-       spin_unlock_irqrestore(&pl330->lock, flags);
-       return ret;
-}
-EXPORT_SYMBOL(pl330_chan_ctrl);
-
-int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus)
-{
-       struct pl330_thread *thrd = ch_id;
-       struct pl330_dmac *pl330;
-       struct pl330_info *pi;
-       void __iomem *regs;
-       int active;
-       u32 val;
-
-       if (!pstatus || !thrd || thrd->free)
-               return -EINVAL;
-
-       pl330 = thrd->dmac;
-       pi = pl330->pinfo;
-       regs = pi->base;
-
-       /* The client should remove the DMAC and add again */
-       if (pl330->state == DYING)
-               pstatus->dmac_halted = true;
-       else
-               pstatus->dmac_halted = false;
-
-       val = readl(regs + FSC);
-       if (val & (1 << thrd->id))
-               pstatus->faulting = true;
-       else
-               pstatus->faulting = false;
-
-       active = thrd->req_running;
-
-       if (active == -1) {
-               /* Indicate that the thread is not running */
-               pstatus->top_req = NULL;
-               pstatus->wait_req = NULL;
-       } else {
-               pstatus->top_req = thrd->req[active].r;
-               pstatus->wait_req = !IS_FREE(&thrd->req[1 - active])
-                                       ? thrd->req[1 - active].r : NULL;
-       }
-
-       pstatus->src_addr = readl(regs + SA(thrd->id));
-       pstatus->dst_addr = readl(regs + DA(thrd->id));
-
-       return 0;
-}
-EXPORT_SYMBOL(pl330_chan_status);
-
-/* Reserve an event */
-static inline int _alloc_event(struct pl330_thread *thrd)
-{
-       struct pl330_dmac *pl330 = thrd->dmac;
-       struct pl330_info *pi = pl330->pinfo;
-       int ev;
-
-       for (ev = 0; ev < pi->pcfg.num_events; ev++)
-               if (pl330->events[ev] == -1) {
-                       pl330->events[ev] = thrd->id;
-                       return ev;
-               }
-
-       return -1;
-}
-
-static bool _chan_ns(const struct pl330_info *pi, int i)
-{
-       return pi->pcfg.irq_ns & (1 << i);
-}
-
-/* Upon success, returns IdentityToken for the
- * allocated channel, NULL otherwise.
- */
-void *pl330_request_channel(const struct pl330_info *pi)
-{
-       struct pl330_thread *thrd = NULL;
-       struct pl330_dmac *pl330;
-       unsigned long flags;
-       int chans, i;
-
-       if (!pi || !pi->pl330_data)
-               return NULL;
-
-       pl330 = pi->pl330_data;
-
-       if (pl330->state == DYING)
-               return NULL;
-
-       chans = pi->pcfg.num_chan;
-
-       spin_lock_irqsave(&pl330->lock, flags);
-
-       for (i = 0; i < chans; i++) {
-               thrd = &pl330->channels[i];
-               if ((thrd->free) && (!_manager_ns(thrd) ||
-                                       _chan_ns(pi, i))) {
-                       thrd->ev = _alloc_event(thrd);
-                       if (thrd->ev >= 0) {
-                               thrd->free = false;
-                               thrd->lstenq = 1;
-                               thrd->req[0].r = NULL;
-                               mark_free(thrd, 0);
-                               thrd->req[1].r = NULL;
-                               mark_free(thrd, 1);
-                               break;
-                       }
-               }
-               thrd = NULL;
-       }
-
-       spin_unlock_irqrestore(&pl330->lock, flags);
-
-       return thrd;
-}
-EXPORT_SYMBOL(pl330_request_channel);
-
-/* Release an event */
-static inline void _free_event(struct pl330_thread *thrd, int ev)
-{
-       struct pl330_dmac *pl330 = thrd->dmac;
-       struct pl330_info *pi = pl330->pinfo;
-
-       /* If the event is valid and was held by the thread */
-       if (ev >= 0 && ev < pi->pcfg.num_events
-                       && pl330->events[ev] == thrd->id)
-               pl330->events[ev] = -1;
-}
-
-void pl330_release_channel(void *ch_id)
-{
-       struct pl330_thread *thrd = ch_id;
-       struct pl330_dmac *pl330;
-       unsigned long flags;
-
-       if (!thrd || thrd->free)
-               return;
-
-       _stop(thrd);
-
-       _callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT);
-       _callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT);
-
-       pl330 = thrd->dmac;
-
-       spin_lock_irqsave(&pl330->lock, flags);
-       _free_event(thrd, thrd->ev);
-       thrd->free = true;
-       spin_unlock_irqrestore(&pl330->lock, flags);
-}
-EXPORT_SYMBOL(pl330_release_channel);
-
-/* Initialize the structure for PL330 configuration, that can be used
- * by the client driver the make best use of the DMAC
- */
-static void read_dmac_config(struct pl330_info *pi)
-{
-       void __iomem *regs = pi->base;
-       u32 val;
-
-       val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
-       val &= CRD_DATA_WIDTH_MASK;
-       pi->pcfg.data_bus_width = 8 * (1 << val);
-
-       val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
-       val &= CRD_DATA_BUFF_MASK;
-       pi->pcfg.data_buf_dep = val + 1;
-
-       val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
-       val &= CR0_NUM_CHANS_MASK;
-       val += 1;
-       pi->pcfg.num_chan = val;
-
-       val = readl(regs + CR0);
-       if (val & CR0_PERIPH_REQ_SET) {
-               val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
-               val += 1;
-               pi->pcfg.num_peri = val;
-               pi->pcfg.peri_ns = readl(regs + CR4);
-       } else {
-               pi->pcfg.num_peri = 0;
-       }
-
-       val = readl(regs + CR0);
-       if (val & CR0_BOOT_MAN_NS)
-               pi->pcfg.mode |= DMAC_MODE_NS;
-       else
-               pi->pcfg.mode &= ~DMAC_MODE_NS;
-
-       val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
-       val &= CR0_NUM_EVENTS_MASK;
-       val += 1;
-       pi->pcfg.num_events = val;
-
-       pi->pcfg.irq_ns = readl(regs + CR3);
-
-       pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
-       pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
-}
-
-static inline void _reset_thread(struct pl330_thread *thrd)
-{
-       struct pl330_dmac *pl330 = thrd->dmac;
-       struct pl330_info *pi = pl330->pinfo;
-
-       thrd->req[0].mc_cpu = pl330->mcode_cpu
-                               + (thrd->id * pi->mcbufsz);
-       thrd->req[0].mc_bus = pl330->mcode_bus
-                               + (thrd->id * pi->mcbufsz);
-       thrd->req[0].r = NULL;
-       mark_free(thrd, 0);
-
-       thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
-                               + pi->mcbufsz / 2;
-       thrd->req[1].mc_bus = thrd->req[0].mc_bus
-                               + pi->mcbufsz / 2;
-       thrd->req[1].r = NULL;
-       mark_free(thrd, 1);
-}
-
-static int dmac_alloc_threads(struct pl330_dmac *pl330)
-{
-       struct pl330_info *pi = pl330->pinfo;
-       int chans = pi->pcfg.num_chan;
-       struct pl330_thread *thrd;
-       int i;
-
-       /* Allocate 1 Manager and 'chans' Channel threads */
-       pl330->channels = kzalloc((1 + chans) * sizeof(*thrd),
-                                       GFP_KERNEL);
-       if (!pl330->channels)
-               return -ENOMEM;
-
-       /* Init Channel threads */
-       for (i = 0; i < chans; i++) {
-               thrd = &pl330->channels[i];
-               thrd->id = i;
-               thrd->dmac = pl330;
-               _reset_thread(thrd);
-               thrd->free = true;
-       }
-
-       /* MANAGER is indexed at the end */
-       thrd = &pl330->channels[chans];
-       thrd->id = chans;
-       thrd->dmac = pl330;
-       thrd->free = false;
-       pl330->manager = thrd;
-
-       return 0;
-}
-
-static int dmac_alloc_resources(struct pl330_dmac *pl330)
-{
-       struct pl330_info *pi = pl330->pinfo;
-       int chans = pi->pcfg.num_chan;
-       int ret;
-
-       /*
-        * Alloc MicroCode buffer for 'chans' Channel threads.
-        * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN)
-        */
-       pl330->mcode_cpu = dma_alloc_coherent(pi->dev,
-                               chans * pi->mcbufsz,
-                               &pl330->mcode_bus, GFP_KERNEL);
-       if (!pl330->mcode_cpu) {
-               dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
-                       __func__, __LINE__);
-               return -ENOMEM;
-       }
-
-       ret = dmac_alloc_threads(pl330);
-       if (ret) {
-               dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n",
-                       __func__, __LINE__);
-               dma_free_coherent(pi->dev,
-                               chans * pi->mcbufsz,
-                               pl330->mcode_cpu, pl330->mcode_bus);
-               return ret;
-       }
-
-       return 0;
-}
-
-int pl330_add(struct pl330_info *pi)
-{
-       struct pl330_dmac *pl330;
-       void __iomem *regs;
-       int i, ret;
-
-       if (!pi || !pi->dev)
-               return -EINVAL;
-
-       /* If already added */
-       if (pi->pl330_data)
-               return -EINVAL;
-
-       /*
-        * If the SoC can perform reset on the DMAC, then do it
-        * before reading its configuration.
-        */
-       if (pi->dmac_reset)
-               pi->dmac_reset(pi);
-
-       regs = pi->base;
-
-       /* Check if we can handle this DMAC */
-       if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
-          || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
-               dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-                       get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
-               return -EINVAL;
-       }
-
-       /* Read the configuration of the DMAC */
-       read_dmac_config(pi);
-
-       if (pi->pcfg.num_events == 0) {
-               dev_err(pi->dev, "%s:%d Can't work without events!\n",
-                       __func__, __LINE__);
-               return -EINVAL;
-       }
-
-       pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL);
-       if (!pl330) {
-               dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
-                       __func__, __LINE__);
-               return -ENOMEM;
-       }
-
-       /* Assign the info structure and private data */
-       pl330->pinfo = pi;
-       pi->pl330_data = pl330;
-
-       spin_lock_init(&pl330->lock);
-
-       INIT_LIST_HEAD(&pl330->req_done);
-
-       /* Use default MC buffer size if not provided */
-       if (!pi->mcbufsz)
-               pi->mcbufsz = MCODE_BUFF_PER_REQ * 2;
-
-       /* Mark all events as free */
-       for (i = 0; i < pi->pcfg.num_events; i++)
-               pl330->events[i] = -1;
-
-       /* Allocate resources needed by the DMAC */
-       ret = dmac_alloc_resources(pl330);
-       if (ret) {
-               dev_err(pi->dev, "Unable to create channels for DMAC\n");
-               kfree(pl330);
-               return ret;
-       }
-
-       tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330);
-
-       pl330->state = INIT;
-
-       return 0;
-}
-EXPORT_SYMBOL(pl330_add);
-
-static int dmac_free_threads(struct pl330_dmac *pl330)
-{
-       struct pl330_info *pi = pl330->pinfo;
-       int chans = pi->pcfg.num_chan;
-       struct pl330_thread *thrd;
-       int i;
-
-       /* Release Channel threads */
-       for (i = 0; i < chans; i++) {
-               thrd = &pl330->channels[i];
-               pl330_release_channel((void *)thrd);
-       }
-
-       /* Free memory */
-       kfree(pl330->channels);
-
-       return 0;
-}
-
-static void dmac_free_resources(struct pl330_dmac *pl330)
-{
-       struct pl330_info *pi = pl330->pinfo;
-       int chans = pi->pcfg.num_chan;
-
-       dmac_free_threads(pl330);
-
-       dma_free_coherent(pi->dev, chans * pi->mcbufsz,
-                               pl330->mcode_cpu, pl330->mcode_bus);
-}
-
-void pl330_del(struct pl330_info *pi)
-{
-       struct pl330_dmac *pl330;
-
-       if (!pi || !pi->pl330_data)
-               return;
-
-       pl330 = pi->pl330_data;
-
-       pl330->state = UNINIT;
-
-       tasklet_kill(&pl330->tasks);
-
-       /* Free DMAC resources */
-       dmac_free_resources(pl330);
-
-       kfree(pl330);
-       pi->pl330_data = NULL;
-}
-EXPORT_SYMBOL(pl330_del);
index 67dd2affc57a3ed607bd431f662851ae27a57779..1171a5010aeaa1fdf1a8c678b29d7a69936b08a9 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #include <asm/mach/pci.h>
 
index 1103f62a1964e86b799534af2ebd0c535bc64854..a8314c3ee84d554b3cbecb3fbb9b1cc4dd450c9a 100644 (file)
@@ -57,18 +57,24 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCI=y
 CONFIG_E100=y
+CONFIG_SMC91X=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIAL_AMBA_PL010=y
 CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_ARMCLCD=y
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PL030=y
 CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
@@ -78,5 +84,7 @@ CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
index 23371b17b23ebfa3a5a987eeb0aa0065660a37e1..03fb93621d0d6046b7b416c9c4328437380fd843 100644 (file)
@@ -23,6 +23,8 @@
 #include <asm/ptrace.h>
 #include <asm/domain.h>
 
+#define IOMEM(x)       (x)
+
 /*
  * Endian independent macros for shifting bytes within registers.
  */
index 86976d03438213975c0aae962012f15b89275de8..68374ba6a943e9d029246d927b64a52913ea525e 100644 (file)
@@ -13,7 +13,9 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
+#include <asm/barrier.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i) { (i) }
 
diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..44f4a09
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
+#if __LINUX_ARM_ARCH__ >= 7 ||         \
+       (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
+#define sev()  __asm__ __volatile__ ("sev" : : : "memory")
+#define wfe()  __asm__ __volatile__ ("wfe" : : : "memory")
+#define wfi()  __asm__ __volatile__ ("wfi" : : : "memory")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+#define isb() __asm__ __volatile__ ("isb" : : : "memory")
+#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
+#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
+#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+                                   : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+                                   : : "r" (0) : "memory")
+#elif defined(CONFIG_CPU_FA526)
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+                                   : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#else
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif
+
+#ifdef CONFIG_ARCH_HAS_BARRIERS
+#include <mach/barriers.h>
+#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
+#include <asm/outercache.h>
+#define mb()           do { dsb(); outer_sync(); } while (0)
+#define rmb()          dsb()
+#define wmb()          mb()
+#else
+#include <asm/memory.h>
+#define mb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#define rmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#define wmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#endif
+
+#ifndef CONFIG_SMP
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#else
+#define smp_mb()       dmb()
+#define smp_rmb()      dmb()
+#define smp_wmb()      dmb()
+#endif
+
+#define read_barrier_depends()         do { } while(0)
+#define smp_read_barrier_depends()     do { } while(0)
+
+#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_BARRIER_H */
index f7419ef9c8f99f57a0495bf31453580c6ed43893..e691ec91e4d339648e4b64733e23999570940d62 100644 (file)
@@ -24,7 +24,7 @@
 #endif
 
 #include <linux/compiler.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
 
 #define smp_mb__before_clear_bit()     smp_mb()
 #define smp_mb__after_clear_bit()      smp_mb()
index fac79dceb7361b411eafad341d824f1eef7b7bfb..7af5c6c3653a8061bad62211bbd3073af82ab3f0 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASMARM_BUG_H
 #define _ASMARM_BUG_H
 
+#include <linux/linkage.h>
 
 #ifdef CONFIG_BUG
 
@@ -57,4 +58,33 @@ do {                                                         \
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+void die(const char *msg, struct pt_regs *regs, int err);
+
+struct siginfo;
+void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
+               unsigned long err, unsigned long trap);
+
+#ifdef CONFIG_ARM_LPAE
+#define FAULT_CODE_ALIGNMENT   33
+#define FAULT_CODE_DEBUG       34
+#else
+#define FAULT_CODE_ALIGNMENT   1
+#define FAULT_CODE_DEBUG       2
+#endif
+
+void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
+                                      struct pt_regs *),
+                    int sig, int code, const char *name);
+
+void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
+                                      struct pt_regs *),
+                    int sig, int code, const char *name);
+
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+struct mm_struct;
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+extern void __show_regs(struct pt_regs *);
+
 #endif
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..d41d7cb
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef __ASM_ARM_CMPXCHG_H
+#define __ASM_ARM_CMPXCHG_H
+
+#include <linux/irqflags.h>
+#include <asm/barrier.h>
+
+#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
+/*
+ * On the StrongARM, "swp" is terminally broken since it bypasses the
+ * cache totally.  This means that the cache becomes inconsistent, and,
+ * since we use normal loads/stores as well, this is really bad.
+ * Typically, this causes oopsen in filp_close, but could have other,
+ * more disastrous effects.  There are two work-arounds:
+ *  1. Disable interrupts and emulate the atomic swap
+ *  2. Clean the cache, perform atomic swap, flush the cache
+ *
+ * We choose (1) since its the "easiest" to achieve here and is not
+ * dependent on the processor type.
+ *
+ * NOTE that this solution won't work on an SMP system, so explcitly
+ * forbid it here.
+ */
+#define swp_is_buggy
+#endif
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+       extern void __bad_xchg(volatile void *, int);
+       unsigned long ret;
+#ifdef swp_is_buggy
+       unsigned long flags;
+#endif
+#if __LINUX_ARM_ARCH__ >= 6
+       unsigned int tmp;
+#endif
+
+       smp_mb();
+
+       switch (size) {
+#if __LINUX_ARM_ARCH__ >= 6
+       case 1:
+               asm volatile("@ __xchg1\n"
+               "1:     ldrexb  %0, [%3]\n"
+               "       strexb  %1, %2, [%3]\n"
+               "       teq     %1, #0\n"
+               "       bne     1b"
+                       : "=&r" (ret), "=&r" (tmp)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       case 4:
+               asm volatile("@ __xchg4\n"
+               "1:     ldrex   %0, [%3]\n"
+               "       strex   %1, %2, [%3]\n"
+               "       teq     %1, #0\n"
+               "       bne     1b"
+                       : "=&r" (ret), "=&r" (tmp)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+#elif defined(swp_is_buggy)
+#ifdef CONFIG_SMP
+#error SMP is not supported on this platform
+#endif
+       case 1:
+               raw_local_irq_save(flags);
+               ret = *(volatile unsigned char *)ptr;
+               *(volatile unsigned char *)ptr = x;
+               raw_local_irq_restore(flags);
+               break;
+
+       case 4:
+               raw_local_irq_save(flags);
+               ret = *(volatile unsigned long *)ptr;
+               *(volatile unsigned long *)ptr = x;
+               raw_local_irq_restore(flags);
+               break;
+#else
+       case 1:
+               asm volatile("@ __xchg1\n"
+               "       swpb    %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       case 4:
+               asm volatile("@ __xchg4\n"
+               "       swp     %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+#endif
+       default:
+               __bad_xchg(ptr, size), ret = 0;
+               break;
+       }
+       smp_mb();
+
+       return ret;
+}
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+#if __LINUX_ARM_ARCH__ < 6
+/* min ARCH < ARMv6 */
+
+#ifdef CONFIG_SMP
+#error "SMP is not supported on this platform"
+#endif
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#else  /* min ARCH >= ARMv6 */
+
+extern void __bad_cmpxchg(volatile void *ptr, int size);
+
+/*
+ * cmpxchg only support 32-bits operands on ARMv6.
+ */
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       unsigned long oldval, res;
+
+       switch (size) {
+#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
+       case 1:
+               do {
+                       asm volatile("@ __cmpxchg1\n"
+                       "       ldrexb  %1, [%2]\n"
+                       "       mov     %0, #0\n"
+                       "       teq     %1, %3\n"
+                       "       strexbeq %0, %4, [%2]\n"
+                               : "=&r" (res), "=&r" (oldval)
+                               : "r" (ptr), "Ir" (old), "r" (new)
+                               : "memory", "cc");
+               } while (res);
+               break;
+       case 2:
+               do {
+                       asm volatile("@ __cmpxchg1\n"
+                       "       ldrexh  %1, [%2]\n"
+                       "       mov     %0, #0\n"
+                       "       teq     %1, %3\n"
+                       "       strexheq %0, %4, [%2]\n"
+                               : "=&r" (res), "=&r" (oldval)
+                               : "r" (ptr), "Ir" (old), "r" (new)
+                               : "memory", "cc");
+               } while (res);
+               break;
+#endif
+       case 4:
+               do {
+                       asm volatile("@ __cmpxchg4\n"
+                       "       ldrex   %1, [%2]\n"
+                       "       mov     %0, #0\n"
+                       "       teq     %1, %3\n"
+                       "       strexeq %0, %4, [%2]\n"
+                               : "=&r" (res), "=&r" (oldval)
+                               : "r" (ptr), "Ir" (old), "r" (new)
+                               : "memory", "cc");
+               } while (res);
+               break;
+       default:
+               __bad_cmpxchg(ptr, size);
+               oldval = 0;
+       }
+
+       return oldval;
+}
+
+static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
+                                        unsigned long new, int size)
+{
+       unsigned long ret;
+
+       smp_mb();
+       ret = __cmpxchg(ptr, old, new, size);
+       smp_mb();
+
+       return ret;
+}
+
+#define cmpxchg(ptr,o,n)                                               \
+       ((__typeof__(*(ptr)))__cmpxchg_mb((ptr),                        \
+                                         (unsigned long)(o),           \
+                                         (unsigned long)(n),           \
+                                         sizeof(*(ptr))))
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                           unsigned long old,
+                                           unsigned long new, int size)
+{
+       unsigned long ret;
+
+       switch (size) {
+#ifdef CONFIG_CPU_V6   /* min ARCH == ARMv6 */
+       case 1:
+       case 2:
+               ret = __cmpxchg_local_generic(ptr, old, new, size);
+               break;
+#endif
+       default:
+               ret = __cmpxchg(ptr, old, new, size);
+       }
+
+       return ret;
+}
+
+#define cmpxchg_local(ptr,o,n)                                         \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr),                     \
+                                      (unsigned long)(o),              \
+                                      (unsigned long)(n),              \
+                                      sizeof(*(ptr))))
+
+#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
+
+/*
+ * Note : ARMv7-M (currently unsupported by Linux) does not support
+ * ldrexd/strexd. If ARMv7-M is ever supported by the Linux kernel, it should
+ * not be allowed to use __cmpxchg64.
+ */
+static inline unsigned long long __cmpxchg64(volatile void *ptr,
+                                            unsigned long long old,
+                                            unsigned long long new)
+{
+       register unsigned long long oldval asm("r0");
+       register unsigned long long __old asm("r2") = old;
+       register unsigned long long __new asm("r4") = new;
+       unsigned long res;
+
+       do {
+               asm volatile(
+               "       @ __cmpxchg8\n"
+               "       ldrexd  %1, %H1, [%2]\n"
+               "       mov     %0, #0\n"
+               "       teq     %1, %3\n"
+               "       teqeq   %H1, %H3\n"
+               "       strexdeq %0, %4, %H4, [%2]\n"
+                       : "=&r" (res), "=&r" (oldval)
+                       : "r" (ptr), "Ir" (__old), "r" (__new)
+                       : "memory", "cc");
+       } while (res);
+
+       return oldval;
+}
+
+static inline unsigned long long __cmpxchg64_mb(volatile void *ptr,
+                                               unsigned long long old,
+                                               unsigned long long new)
+{
+       unsigned long long ret;
+
+       smp_mb();
+       ret = __cmpxchg64(ptr, old, new);
+       smp_mb();
+
+       return ret;
+}
+
+#define cmpxchg64(ptr,o,n)                                             \
+       ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),                      \
+                                           (unsigned long long)(o),    \
+                                           (unsigned long long)(n)))
+
+#define cmpxchg64_local(ptr,o,n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg64((ptr),                         \
+                                        (unsigned long long)(o),       \
+                                        (unsigned long long)(n)))
+
+#else /* min ARCH = ARMv6 */
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif
+
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#endif /* __ASM_ARM_CMPXCHG_H */
diff --git a/arch/arm/include/asm/compiler.h b/arch/arm/include/asm/compiler.h
new file mode 100644 (file)
index 0000000..8155db2
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ASM_ARM_COMPILER_H
+#define __ASM_ARM_COMPILER_H
+
+/*
+ * This is used to ensure the compiler did actually allocate the register we
+ * asked it for some inline assembly sequences.  Apparently we can't trust
+ * the compiler from one version to another so a bit of paranoia won't hurt.
+ * This string is meant to be concatenated with the inline asm string and
+ * will cause compilation to stop on mismatch.
+ * (for details, see gcc PR 15089)
+ */
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+
+#endif /* __ASM_ARM_COMPILER_H */
diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
new file mode 100644 (file)
index 0000000..5ef4d80
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef __ASM_ARM_CP15_H
+#define __ASM_ARM_CP15_H
+
+#include <asm/barrier.h>
+
+/*
+ * CR1 bits (CP#15 CR1)
+ */
+#define CR_M   (1 << 0)        /* MMU enable                           */
+#define CR_A   (1 << 1)        /* Alignment abort enable               */
+#define CR_C   (1 << 2)        /* Dcache enable                        */
+#define CR_W   (1 << 3)        /* Write buffer enable                  */
+#define CR_P   (1 << 4)        /* 32-bit exception handler             */
+#define CR_D   (1 << 5)        /* 32-bit data address range            */
+#define CR_L   (1 << 6)        /* Implementation defined               */
+#define CR_B   (1 << 7)        /* Big endian                           */
+#define CR_S   (1 << 8)        /* System MMU protection                */
+#define CR_R   (1 << 9)        /* ROM MMU protection                   */
+#define CR_F   (1 << 10)       /* Implementation defined               */
+#define CR_Z   (1 << 11)       /* Implementation defined               */
+#define CR_I   (1 << 12)       /* Icache enable                        */
+#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
+#define CR_RR  (1 << 14)       /* Round Robin cache replacement        */
+#define CR_L4  (1 << 15)       /* LDR pc can set T bit                 */
+#define CR_DT  (1 << 16)
+#define CR_IT  (1 << 18)
+#define CR_ST  (1 << 19)
+#define CR_FI  (1 << 21)       /* Fast interrupt (lower latency mode)  */
+#define CR_U   (1 << 22)       /* Unaligned access operation           */
+#define CR_XP  (1 << 23)       /* Extended page tables                 */
+#define CR_VE  (1 << 24)       /* Vectored interrupts                  */
+#define CR_EE  (1 << 25)       /* Exception (Big) Endian               */
+#define CR_TRE (1 << 28)       /* TEX remap enable                     */
+#define CR_AFE (1 << 29)       /* Access flag enable                   */
+#define CR_TE  (1 << 30)       /* Thumb exception enable               */
+
+#ifndef __ASSEMBLY__
+
+#if __LINUX_ARM_ARCH__ >= 4
+#define vectors_high() (cr_alignment & CR_V)
+#else
+#define vectors_high() (0)
+#endif
+
+extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
+extern unsigned long cr_alignment;     /* defined in entry-armv.S */
+
+static inline unsigned int get_cr(void)
+{
+       unsigned int val;
+       asm("mrc p15, 0, %0, c1, c0, 0  @ get CR" : "=r" (val) : : "cc");
+       return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+       asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
+         : : "r" (val) : "cc");
+       isb();
+}
+
+#ifndef CONFIG_SMP
+extern void adjust_cr(unsigned long mask, unsigned long set);
+#endif
+
+#define CPACC_FULL(n)          (3 << (n * 2))
+#define CPACC_SVC(n)           (1 << (n * 2))
+#define CPACC_DISABLE(n)       (0 << (n * 2))
+
+static inline unsigned int get_copro_access(void)
+{
+       unsigned int val;
+       asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access"
+         : "=r" (val) : : "cc");
+       return val;
+}
+
+static inline void set_copro_access(unsigned int val)
+{
+       asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
+         : : "r" (val) : "cc");
+       isb();
+}
+
+#endif
+
+#endif
index d3f0a9eee9f65a94b8b7804c162f65160496b485..fe92ccf1d0b0c7a43417f0d6675516840c149feb 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ASM_ARM_DIV64
 #define __ASM_ARM_DIV64
 
-#include <asm/system.h>
 #include <linux/types.h>
+#include <asm/compiler.h>
 
 /*
  * The semantics of do_div() are:
index 69a5b0b6455c72af47fe8df6db36e310cc97b8f2..5694a0d6576bd41c8a11f95351382e675944338b 100644 (file)
@@ -19,7 +19,6 @@
  * It should not be re-used except for that purpose.
  */
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <asm/scatterlist.h>
 
 #include <mach/isa-dma.h>
index b5dc173d336f93f88d7fa63e0b0c91def5393255..3d2220498abc2db2d98378c94a3309c71e91ccee 100644 (file)
 #ifndef __ASM_PROC_DOMAIN_H
 #define __ASM_PROC_DOMAIN_H
 
+#ifndef __ASSEMBLY__
+#include <asm/barrier.h>
+#endif
+
 /*
  * Domain numbers
  *
index 0e9ce8d9686ee916af2263a42e0ddcd5926cbe53..38050b1c4800b90b190a415b7d173e9948e20b97 100644 (file)
@@ -130,8 +130,4 @@ struct mm_struct;
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
-extern int vectors_user_mapping(void);
-#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
-
 #endif
diff --git a/arch/arm/include/asm/exec.h b/arch/arm/include/asm/exec.h
new file mode 100644 (file)
index 0000000..7c4fbef
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_ARM_EXEC_H
+#define __ASM_ARM_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_ARM_EXEC_H */
index 7df239bcdf2745b6a3d20e5a90ed3bac27d73ecc..c4c87bc1223195478a76547d0e756ddec961eb70 100644 (file)
 #define L2X0_ADDR_FILTER_EN            1
 
 #ifndef __ASSEMBLY__
-extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
 #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
-extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+extern int l2x0_of_init(u32 aux_val, u32 aux_mask);
 #else
-static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)
 {
        return -ENODEV;
 }
index 077c32326c638755d5e195e1a5a9b09edfff2538..2ff2c75a46391344689893b3132b714ca96b8020 100644 (file)
@@ -231,6 +231,9 @@ extern int iop3xx_get_init_atu(void);
 
 
 #ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
 void iop3xx_map_io(void);
 void iop_init_cp6_handler(void);
 void iop_init_time(unsigned long tickrate);
index 59b8c3892f76731608b346d0d100910e9047c481..122f86d8c991d73e587c786eba41bf85a6ec5a21 100644 (file)
@@ -49,7 +49,6 @@ struct iop_adma_device {
 /**
  * struct iop_adma_chan - internal representation of an ADMA device
  * @pending: allows batching of hardware operations
- * @completed_cookie: identifier for the most recently completed operation
  * @lock: serializes enqueue/dequeue operations to the slot pool
  * @mmr_base: memory mapped register base
  * @chain: device chain view of the descriptors
@@ -62,7 +61,6 @@ struct iop_adma_device {
  */
 struct iop_adma_chan {
        int pending;
-       dma_cookie_t completed_cookie;
        spinlock_t lock; /* protects the descriptor slot pool */
        void __iomem *mmr_base;
        struct list_head chain;
index 43cab498bc279c1e6f6078c03717e1c497384680..73f84fa4f366d0b1c4978414a42209e86cc27ab0 100644 (file)
@@ -9,6 +9,9 @@
 
 #ifndef __ASM_HARDWARE_IT8152_H
 #define __ASM_HARDWARE_IT8152_H
+
+#include <mach/irqs.h>
+
 extern void __iomem *it8152_base_address;
 
 #define IT8152_IO_BASE                 (it8152_base_address + 0x03e00000)
diff --git a/arch/arm/include/asm/hardware/pl330.h b/arch/arm/include/asm/hardware/pl330.h
deleted file mode 100644 (file)
index c182138..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/* linux/include/asm/hardware/pl330.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __PL330_CORE_H
-#define __PL330_CORE_H
-
-#define PL330_MAX_CHAN         8
-#define PL330_MAX_IRQS         32
-#define PL330_MAX_PERI         32
-
-enum pl330_srccachectrl {
-       SCCTRL0 = 0, /* Noncacheable and nonbufferable */
-       SCCTRL1, /* Bufferable only */
-       SCCTRL2, /* Cacheable, but do not allocate */
-       SCCTRL3, /* Cacheable and bufferable, but do not allocate */
-       SINVALID1,
-       SINVALID2,
-       SCCTRL6, /* Cacheable write-through, allocate on reads only */
-       SCCTRL7, /* Cacheable write-back, allocate on reads only */
-};
-
-enum pl330_dstcachectrl {
-       DCCTRL0 = 0, /* Noncacheable and nonbufferable */
-       DCCTRL1, /* Bufferable only */
-       DCCTRL2, /* Cacheable, but do not allocate */
-       DCCTRL3, /* Cacheable and bufferable, but do not allocate */
-       DINVALID1,              /* AWCACHE = 0x1000 */
-       DINVALID2,
-       DCCTRL6, /* Cacheable write-through, allocate on writes only */
-       DCCTRL7, /* Cacheable write-back, allocate on writes only */
-};
-
-/* Populated by the PL330 core driver for DMA API driver's info */
-struct pl330_config {
-       u32     periph_id;
-       u32     pcell_id;
-#define DMAC_MODE_NS   (1 << 0)
-       unsigned int    mode;
-       unsigned int    data_bus_width:10; /* In number of bits */
-       unsigned int    data_buf_dep:10;
-       unsigned int    num_chan:4;
-       unsigned int    num_peri:6;
-       u32             peri_ns;
-       unsigned int    num_events:6;
-       u32             irq_ns;
-};
-
-/* Handle to the DMAC provided to the PL330 core */
-struct pl330_info {
-       /* Owning device */
-       struct device *dev;
-       /* Size of MicroCode buffers for each channel. */
-       unsigned mcbufsz;
-       /* ioremap'ed address of PL330 registers. */
-       void __iomem    *base;
-       /* Client can freely use it. */
-       void    *client_data;
-       /* PL330 core data, Client must not touch it. */
-       void    *pl330_data;
-       /* Populated by the PL330 core driver during pl330_add */
-       struct pl330_config     pcfg;
-       /*
-        * If the DMAC has some reset mechanism, then the
-        * client may want to provide pointer to the method.
-        */
-       void (*dmac_reset)(struct pl330_info *pi);
-};
-
-enum pl330_byteswap {
-       SWAP_NO = 0,
-       SWAP_2,
-       SWAP_4,
-       SWAP_8,
-       SWAP_16,
-};
-
-/**
- * Request Configuration.
- * The PL330 core does not modify this and uses the last
- * working configuration if the request doesn't provide any.
- *
- * The Client may want to provide this info only for the
- * first request and a request with new settings.
- */
-struct pl330_reqcfg {
-       /* Address Incrementing */
-       unsigned dst_inc:1;
-       unsigned src_inc:1;
-
-       /*
-        * For now, the SRC & DST protection levels
-        * and burst size/length are assumed same.
-        */
-       bool nonsecure;
-       bool privileged;
-       bool insnaccess;
-       unsigned brst_len:5;
-       unsigned brst_size:3; /* in power of 2 */
-
-       enum pl330_dstcachectrl dcctl;
-       enum pl330_srccachectrl scctl;
-       enum pl330_byteswap swap;
-};
-
-/*
- * One cycle of DMAC operation.
- * There may be more than one xfer in a request.
- */
-struct pl330_xfer {
-       u32 src_addr;
-       u32 dst_addr;
-       /* Size to xfer */
-       u32 bytes;
-       /*
-        * Pointer to next xfer in the list.
-        * The last xfer in the req must point to NULL.
-        */
-       struct pl330_xfer *next;
-};
-
-/* The xfer callbacks are made with one of these arguments. */
-enum pl330_op_err {
-       /* The all xfers in the request were success. */
-       PL330_ERR_NONE,
-       /* If req aborted due to global error. */
-       PL330_ERR_ABORT,
-       /* If req failed due to problem with Channel. */
-       PL330_ERR_FAIL,
-};
-
-enum pl330_reqtype {
-       MEMTOMEM,
-       MEMTODEV,
-       DEVTOMEM,
-       DEVTODEV,
-};
-
-/* A request defining Scatter-Gather List ending with NULL xfer. */
-struct pl330_req {
-       enum pl330_reqtype rqtype;
-       /* Index of peripheral for the xfer. */
-       unsigned peri:5;
-       /* Unique token for this xfer, set by the client. */
-       void *token;
-       /* Callback to be called after xfer. */
-       void (*xfer_cb)(void *token, enum pl330_op_err err);
-       /* If NULL, req will be done at last set parameters. */
-       struct pl330_reqcfg *cfg;
-       /* Pointer to first xfer in the request. */
-       struct pl330_xfer *x;
-};
-
-/*
- * To know the status of the channel and DMAC, the client
- * provides a pointer to this structure. The PL330 core
- * fills it with current information.
- */
-struct pl330_chanstatus {
-       /*
-        * If the DMAC engine halted due to some error,
-        * the client should remove-add DMAC.
-        */
-       bool dmac_halted;
-       /*
-        * If channel is halted due to some error,
-        * the client should ABORT/FLUSH and START the channel.
-        */
-       bool faulting;
-       /* Location of last load */
-       u32 src_addr;
-       /* Location of last store */
-       u32 dst_addr;
-       /*
-        * Pointer to the currently active req, NULL if channel is
-        * inactive, even though the requests may be present.
-        */
-       struct pl330_req *top_req;
-       /* Pointer to req waiting second in the queue if any. */
-       struct pl330_req *wait_req;
-};
-
-enum pl330_chan_op {
-       /* Start the channel */
-       PL330_OP_START,
-       /* Abort the active xfer */
-       PL330_OP_ABORT,
-       /* Stop xfer and flush queue */
-       PL330_OP_FLUSH,
-};
-
-extern int pl330_add(struct pl330_info *);
-extern void pl330_del(struct pl330_info *pi);
-extern int pl330_update(const struct pl330_info *pi);
-extern void pl330_release_channel(void *ch_id);
-extern void *pl330_request_channel(const struct pl330_info *pi);
-extern int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus);
-extern int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op);
-extern int pl330_submit_req(void *ch_id, struct pl330_req *r);
-
-#endif /* __PL330_CORE_H */
index 9275828feb3df24f481934a080572f8d53be3136..df0ac0bb39aae43d6ebf92a7271c4ba7e536f151 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
-#include <asm/system.h>
 #include <asm-generic/pci_iomap.h>
 
 /*
@@ -83,6 +82,11 @@ extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, uns
 extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
 extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached);
 extern void __iounmap(volatile void __iomem *addr);
+extern void __arm_iounmap(volatile void __iomem *addr);
+
+extern void __iomem * (*arch_ioremap_caller)(unsigned long, size_t,
+       unsigned int, void *);
+extern void (*arch_iounmap)(volatile void __iomem *);
 
 /*
  * Bad read/write accesses...
@@ -97,8 +101,11 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
        return (void __iomem *)addr;
 }
 
+#define IOMEM(x)       ((void __force __iomem *)(x))
+
 /* IO barriers */
 #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+#include <asm/barrier.h>
 #define __iormb()              rmb()
 #define __iowmb()              wmb()
 #else
@@ -109,7 +116,11 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
 /*
  * Now, pick up the machine-defined IO definitions
  */
+#ifdef CONFIG_NEED_MACH_IO_H
 #include <mach/io.h>
+#else
+#define __io(a)                ({ (void)(a); __typesafe_io(0); })
+#endif
 
 /*
  * This is the limit of PC card/PCI/ISA IO space, which is by default
@@ -211,18 +222,18 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  * Again, this are defined to perform little endian accesses.  See the
  * IO port primitives for more information.
  */
-#ifdef __mem_pci
-#define readb_relaxed(c) ({ u8  __r = __raw_readb(__mem_pci(c)); __r; })
+#ifndef readl
+#define readb_relaxed(c) ({ u8  __r = __raw_readb(c); __r; })
 #define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
-                                       __raw_readw(__mem_pci(c))); __r; })
+                                       __raw_readw(c)); __r; })
 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
-                                       __raw_readl(__mem_pci(c))); __r; })
+                                       __raw_readl(c)); __r; })
 
-#define writeb_relaxed(v,c)    ((void)__raw_writeb(v,__mem_pci(c)))
+#define writeb_relaxed(v,c)    ((void)__raw_writeb(v,c))
 #define writew_relaxed(v,c)    ((void)__raw_writew((__force u16) \
-                                       cpu_to_le16(v),__mem_pci(c)))
+                                       cpu_to_le16(v),c))
 #define writel_relaxed(v,c)    ((void)__raw_writel((__force u32) \
-                                       cpu_to_le32(v),__mem_pci(c)))
+                                       cpu_to_le32(v),c))
 
 #define readb(c)               ({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)               ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
@@ -232,30 +243,19 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 #define writew(v,c)            ({ __iowmb(); writew_relaxed(v,c); })
 #define writel(v,c)            ({ __iowmb(); writel_relaxed(v,c); })
 
-#define readsb(p,d,l)          __raw_readsb(__mem_pci(p),d,l)
-#define readsw(p,d,l)          __raw_readsw(__mem_pci(p),d,l)
-#define readsl(p,d,l)          __raw_readsl(__mem_pci(p),d,l)
-
-#define writesb(p,d,l)         __raw_writesb(__mem_pci(p),d,l)
-#define writesw(p,d,l)         __raw_writesw(__mem_pci(p),d,l)
-#define writesl(p,d,l)         __raw_writesl(__mem_pci(p),d,l)
+#define readsb(p,d,l)          __raw_readsb(p,d,l)
+#define readsw(p,d,l)          __raw_readsw(p,d,l)
+#define readsl(p,d,l)          __raw_readsl(p,d,l)
 
-#define memset_io(c,v,l)       _memset_io(__mem_pci(c),(v),(l))
-#define memcpy_fromio(a,c,l)   _memcpy_fromio((a),__mem_pci(c),(l))
-#define memcpy_toio(c,a,l)     _memcpy_toio(__mem_pci(c),(a),(l))
+#define writesb(p,d,l)         __raw_writesb(p,d,l)
+#define writesw(p,d,l)         __raw_writesw(p,d,l)
+#define writesl(p,d,l)         __raw_writesl(p,d,l)
 
-#elif !defined(readb)
+#define memset_io(c,v,l)       _memset_io(c,(v),(l))
+#define memcpy_fromio(a,c,l)   _memcpy_fromio((a),c,(l))
+#define memcpy_toio(c,a,l)     _memcpy_toio(c,(a),(l))
 
-#define readb(c)                       (__readwrite_bug("readb"),0)
-#define readw(c)                       (__readwrite_bug("readw"),0)
-#define readl(c)                       (__readwrite_bug("readl"),0)
-#define writeb(v,c)                    __readwrite_bug("writeb")
-#define writew(v,c)                    __readwrite_bug("writew")
-#define writel(v,c)                    __readwrite_bug("writel")
-
-#define check_signature(io,sig,len)    (0)
-
-#endif /* __mem_pci */
+#endif /* readl */
 
 /*
  * ioremap and friends.
@@ -264,16 +264,11 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  * Documentation/io-mapping.txt.
  *
  */
-#ifndef __arch_ioremap
-#define __arch_ioremap                 __arm_ioremap
-#define __arch_iounmap                 __iounmap
-#endif
-
-#define ioremap(cookie,size)           __arch_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_nocache(cookie,size)   __arch_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
-#define ioremap_wc(cookie,size)                __arch_ioremap((cookie), (size), MT_DEVICE_WC)
-#define iounmap                                __arch_iounmap
+#define ioremap(cookie,size)           __arm_ioremap((cookie), (size), MT_DEVICE)
+#define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
+#define ioremap_cached(cookie,size)    __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_wc(cookie,size)                __arm_ioremap((cookie), (size), MT_DEVICE_WC)
+#define iounmap                                __arm_iounmap
 
 /*
  * io{read,write}{8,16,32} macros
index 5a526afb5f1858615ec02928f2e2010b3a25982d..35c21c375d81c19121495c66114ead04044f0fa3 100644 (file)
@@ -1,14 +1,18 @@
 #ifndef __ASM_ARM_IRQ_H
 #define __ASM_ARM_IRQ_H
 
+#define NR_IRQS_LEGACY 16
+
+#ifndef CONFIG_SPARSE_IRQ
 #include <mach/irqs.h>
+#else
+#define NR_IRQS NR_IRQS_LEGACY
+#endif
 
 #ifndef irq_canonicalize
 #define irq_canonicalize(i)    (i)
 #endif
 
-#define NR_IRQS_LEGACY 16
-
 /*
  * Use this value to indicate lack of interrupt
  * capability
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
new file mode 100644 (file)
index 0000000..5c5ca2e
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _ASM_ARM_JUMP_LABEL_H
+#define _ASM_ARM_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define JUMP_LABEL_NOP "nop.w"
+#else
+#define JUMP_LABEL_NOP "nop"
+#endif
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+       asm goto("1:\n\t"
+                JUMP_LABEL_NOP "\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".word 1b, %l[l_yes], %c0\n\t"
+                ".popsection\n\t"
+                : :  "i" (key) :  : l_yes);
+
+       return false;
+l_yes:
+       return true;
+}
+
+#endif /* __KERNEL__ */
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+       jump_label_t code;
+       jump_label_t target;
+       jump_label_t key;
+};
+
+#endif
index 6b884d2b0b69eaf0395040d9d440b93cf0f274d1..e8567bb99dfc5531012c14976f3f93f57615cf58 100644 (file)
@@ -5,7 +5,9 @@
 #define _ASM_MC146818RTC_H
 
 #include <linux/io.h>
-#include <mach/irqs.h>
+#include <linux/kernel.h>
+
+#define RTC_IRQ BUILD_BUG_ON(1)
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)    (0x70 + (x))
index a8997d71084e23b9343b27b650166ba715b96db1..fcb575747e5eb66082a9a7c96bbc6391a767faf5 100644 (file)
 #define MODULES_END            (END_MEM)
 #define MODULES_VADDR          (PHYS_OFFSET)
 
+#define XIP_VIRT_ADDR(physaddr)  (physaddr)
+
 #endif /* !CONFIG_MMU */
 
 /*
index 14965658a923c5e99c009292ddc99f06d013738a..b8e580a297e49d748d12b1ac17fb6519e8d151b2 100644 (file)
@@ -34,4 +34,11 @@ typedef struct {
 
 #endif
 
+/*
+ * switch_mm() may do a full cache flush over the context switch,
+ * so enable interrupts over the context switch to avoid high
+ * latency.
+ */
+#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+
 #endif
index 71605d9f8e421ad36a058992c032ad5459114929..a0b3cac0547c0a9949c30cc919adcf5e08fcf500 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/proc-fns.h>
+#include <asm-generic/mm_hooks.h>
 
 void __check_kvm_seq(struct mm_struct *mm);
 
@@ -133,32 +134,4 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 #define deactivate_mm(tsk,mm)  do { } while (0)
 #define activate_mm(prev,next) switch_mm(prev, next, NULL)
 
-/*
- * We are inserting a "fake" vma for the user-accessible vector page so
- * gdb and friends can get to it through ptrace and /proc/<pid>/mem.
- * But we also want to remove it before the generic code gets to see it
- * during process exit or the unmapping of it would  cause total havoc.
- * (the macro is used as remove_vma() is static to mm/mmap.c)
- */
-#define arch_exit_mmap(mm) \
-do { \
-       struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
-       if (high_vma) { \
-               BUG_ON(high_vma->vm_next);  /* it should be last */ \
-               if (high_vma->vm_prev) \
-                       high_vma->vm_prev->vm_next = NULL; \
-               else \
-                       mm->mmap = NULL; \
-               rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
-               mm->mmap_cache = NULL; \
-               mm->map_count--; \
-               remove_vma(high_vma); \
-       } \
-} while (0)
-
-static inline void arch_dup_mmap(struct mm_struct *oldmm,
-                                struct mm_struct *mm)
-{
-}
-
 #endif
index c0efdd60966f11fc38d6d16ebf829ee2354ef279..19c48deda70f1b759b94b3a852dc0b4f207adfd8 100644 (file)
@@ -17,4 +17,63 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
 #define ARM_OPCODE_CONDTEST_PASS   1
 #define ARM_OPCODE_CONDTEST_UNCOND 2
 
+
+/*
+ * Opcode byteswap helpers
+ *
+ * These macros help with converting instructions between a canonical integer
+ * format and in-memory representation, in an endianness-agnostic manner.
+ *
+ * __mem_to_opcode_*() convert from in-memory representation to canonical form.
+ * __opcode_to_mem_*() convert from canonical form to in-memory representation.
+ *
+ *
+ * Canonical instruction representation:
+ *
+ *     ARM:            0xKKLLMMNN
+ *     Thumb 16-bit:   0x0000KKLL, where KK < 0xE8
+ *     Thumb 32-bit:   0xKKLLMMNN, where KK >= 0xE8
+ *
+ * There is no way to distinguish an ARM instruction in canonical representation
+ * from a Thumb instruction (just as these cannot be distinguished in memory).
+ * Where this distinction is important, it needs to be tracked separately.
+ *
+ * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
+ * represent any valid Thumb-2 instruction.  For this range,
+ * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/swab.h>
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define __opcode_to_mem_arm(x) swab32(x)
+#define __opcode_to_mem_thumb16(x) swab16(x)
+#define __opcode_to_mem_thumb32(x) swahb32(x)
+#else
+#define __opcode_to_mem_arm(x) ((u32)(x))
+#define __opcode_to_mem_thumb16(x) ((u16)(x))
+#define __opcode_to_mem_thumb32(x) swahw32(x)
+#endif
+
+#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
+#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
+#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
+
+/* Operations specific to Thumb opcodes */
+
+/* Instruction size checks: */
+#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
+#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
+
+/* Operations to construct or split 32-bit Thumb instructions: */
+#define __opcode_thumb32_first(x) ((u16)((x) >> 16))
+#define __opcode_thumb32_second(x) ((u16)(x))
+#define __opcode_thumb32_compose(first, second) \
+       (((u32)(u16)(first) << 16) | (u32)(u16)(second))
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ASM_ARM_OPCODES_H */
index 97b440c25c5855977481a40ba18977f1f988dd09..5838361c48b335040c892233da299605ce9e089f 100644 (file)
@@ -151,6 +151,8 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
+#define __HAVE_ARCH_GATE_AREA 1
+
 #ifdef CONFIG_ARM_LPAE
 #include <asm/pgtable-3level-types.h>
 #else
index 7523340afb8a13a15f389537d0f3d432e257cf7d..00cbe10a50e3693b32afe48d0d20e3787e9183d0 100644 (file)
@@ -22,6 +22,7 @@ enum arm_perf_pmu_ids {
        ARM_PERF_PMU_ID_CA9,
        ARM_PERF_PMU_ID_CA5,
        ARM_PERF_PMU_ID_CA15,
+       ARM_PERF_PMU_ID_CA7,
        ARM_NUM_PMU_IDS,
 };
 
index 2446d23bfdbffcfea8dd7e3374ab6a2955ff9ce6..efdf99045d879e240b9bc41f1f0781efea6ac10f 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long          __kernel_ino_t;
 typedef unsigned short         __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short         __kernel_nlink_t;
-typedef long                   __kernel_off_t;
-typedef int                    __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short         __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short         __kernel_uid_t;
 typedef unsigned short         __kernel_gid_t;
-typedef unsigned int           __kernel_size_t;
-typedef int                    __kernel_ssize_t;
-typedef int                    __kernel_ptrdiff_t;
-typedef long                   __kernel_time_t;
-typedef long                   __kernel_suseconds_t;
-typedef long                   __kernel_clock_t;
-typedef int                    __kernel_timer_t;
-typedef int                    __kernel_clockid_t;
-typedef int                    __kernel_daddr_t;
-typedef char *                 __kernel_caddr_t;
-typedef unsigned short         __kernel_uid16_t;
-typedef unsigned short         __kernel_gid16_t;
-typedef unsigned int           __kernel_uid32_t;
-typedef unsigned int           __kernel_gid32_t;
+#define __kernel_uid_t __kernel_uid_t
 
-typedef unsigned short         __kernel_old_uid_t;
-typedef unsigned short         __kernel_old_gid_t;
 typedef unsigned short         __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __GNUC__
-typedef long long              __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-#define __FD_SET(fd, fdsetp) \
-               (((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] |= (1<<((fd) & 31)))
-
-#undef __FD_CLR
-#define __FD_CLR(fd, fdsetp) \
-               (((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] &= ~(1<<((fd) & 31)))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd, fdsetp) \
-               ((((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] & (1<<((fd) & 31))) != 0)
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) \
-               (memset (fdsetp, 0, sizeof (*(fd_set *)(fdsetp))))
-
-#endif
+#include <asm-generic/posix_types.h>
 
 #endif
index cb8d638924fd3d6f0abfa1a6dc589a755b3bc79b..5ac8d3d3e0259cc8ceaa16b7ac7caa6facf177f7 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
-#include <asm/system.h>
 
 #ifdef __KERNEL__
 #define STACK_TOP      ((current->personality & ADDR_LIMIT_32BIT) ? \
@@ -56,7 +55,6 @@ struct thread_struct {
 #define start_thread(regs,pc,sp)                                       \
 ({                                                                     \
        unsigned long *stack = (unsigned long *)sp;                     \
-       set_fs(USER_DS);                                                \
        memset(regs->uregs, 0, sizeof(regs->uregs));                    \
        if (current->personality & ADDR_LIMIT_32BIT)                    \
                regs->ARM_cpsr = USR_MODE;                              \
@@ -90,6 +88,8 @@ unsigned long get_wchan(struct task_struct *p);
 #define cpu_relax()                    barrier()
 #endif
 
+void cpu_idle_wait(void);
+
 /*
  * Create a new kernel thread
  */
index ee0363307918b1d889897553f0283e0848307b15..aeae9c609df4885570646d076741cef0565328da 100644 (file)
@@ -13,8 +13,6 @@
 
 #ifdef CONFIG_OF
 
-#include <asm/irq.h>
-
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 
diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..fa09e6b
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __ASM_ARM_SWITCH_TO_H
+#define __ASM_ARM_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.  schedule() itself
+ * contains the memory barrier to tell GCC not to cache `current'.
+ */
+extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
+
+#define switch_to(prev,next,last)                                      \
+do {                                                                   \
+       last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
+} while (0)
+
+#endif /* __ASM_ARM_SWITCH_TO_H */
index 424aa458c4873dd8556f655115946d5c898c3e47..74542c52f9befa1d5f614b3d223291f0d4a0d2c4 100644 (file)
@@ -1,544 +1,8 @@
-#ifndef __ASM_ARM_SYSTEM_H
-#define __ASM_ARM_SYSTEM_H
-
-#ifdef __KERNEL__
-
-#define CPU_ARCH_UNKNOWN       0
-#define CPU_ARCH_ARMv3         1
-#define CPU_ARCH_ARMv4         2
-#define CPU_ARCH_ARMv4T                3
-#define CPU_ARCH_ARMv5         4
-#define CPU_ARCH_ARMv5T                5
-#define CPU_ARCH_ARMv5TE       6
-#define CPU_ARCH_ARMv5TEJ      7
-#define CPU_ARCH_ARMv6         8
-#define CPU_ARCH_ARMv7         9
-
-/*
- * CR1 bits (CP#15 CR1)
- */
-#define CR_M   (1 << 0)        /* MMU enable                           */
-#define CR_A   (1 << 1)        /* Alignment abort enable               */
-#define CR_C   (1 << 2)        /* Dcache enable                        */
-#define CR_W   (1 << 3)        /* Write buffer enable                  */
-#define CR_P   (1 << 4)        /* 32-bit exception handler             */
-#define CR_D   (1 << 5)        /* 32-bit data address range            */
-#define CR_L   (1 << 6)        /* Implementation defined               */
-#define CR_B   (1 << 7)        /* Big endian                           */
-#define CR_S   (1 << 8)        /* System MMU protection                */
-#define CR_R   (1 << 9)        /* ROM MMU protection                   */
-#define CR_F   (1 << 10)       /* Implementation defined               */
-#define CR_Z   (1 << 11)       /* Implementation defined               */
-#define CR_I   (1 << 12)       /* Icache enable                        */
-#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
-#define CR_RR  (1 << 14)       /* Round Robin cache replacement        */
-#define CR_L4  (1 << 15)       /* LDR pc can set T bit                 */
-#define CR_DT  (1 << 16)
-#define CR_IT  (1 << 18)
-#define CR_ST  (1 << 19)
-#define CR_FI  (1 << 21)       /* Fast interrupt (lower latency mode)  */
-#define CR_U   (1 << 22)       /* Unaligned access operation           */
-#define CR_XP  (1 << 23)       /* Extended page tables                 */
-#define CR_VE  (1 << 24)       /* Vectored interrupts                  */
-#define CR_EE  (1 << 25)       /* Exception (Big) Endian               */
-#define CR_TRE (1 << 28)       /* TEX remap enable                     */
-#define CR_AFE (1 << 29)       /* Access flag enable                   */
-#define CR_TE  (1 << 30)       /* Thumb exception enable               */
-
-/*
- * This is used to ensure the compiler did actually allocate the register we
- * asked it for some inline assembly sequences.  Apparently we can't trust
- * the compiler from one version to another so a bit of paranoia won't hurt.
- * This string is meant to be concatenated with the inline asm string and
- * will cause compilation to stop on mismatch.
- * (for details, see gcc PR 15089)
- */
-#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
-
-#ifndef __ASSEMBLY__
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-#include <asm/outercache.h>
-
-struct thread_info;
-struct task_struct;
-
-/* information about the system we're running on */
-extern unsigned int system_rev;
-extern unsigned int system_serial_low;
-extern unsigned int system_serial_high;
-extern unsigned int mem_fclk_21285;
-
-struct pt_regs;
-
-void die(const char *msg, struct pt_regs *regs, int err);
-
-struct siginfo;
-void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
-               unsigned long err, unsigned long trap);
-
-#ifdef CONFIG_ARM_LPAE
-#define FAULT_CODE_ALIGNMENT   33
-#define FAULT_CODE_DEBUG       34
-#else
-#define FAULT_CODE_ALIGNMENT   1
-#define FAULT_CODE_DEBUG       2
-#endif
-
-void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
-                                      struct pt_regs *),
-                    int sig, int code, const char *name);
-
-void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
-                                      struct pt_regs *),
-                    int sig, int code, const char *name);
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-struct mm_struct;
-extern void show_pte(struct mm_struct *mm, unsigned long addr);
-extern void __show_regs(struct pt_regs *);
-
-extern int __pure cpu_architecture(void);
-extern void cpu_init(void);
-
-void soft_restart(unsigned long);
-extern void (*arm_pm_restart)(char str, const char *cmd);
-extern void (*arm_pm_idle)(void);
-
-#define UDBG_UNDEFINED (1 << 0)
-#define UDBG_SYSCALL   (1 << 1)
-#define UDBG_BADABORT  (1 << 2)
-#define UDBG_SEGV      (1 << 3)
-#define UDBG_BUS       (1 << 4)
-
-extern unsigned int user_debug;
-
-#if __LINUX_ARM_ARCH__ >= 4
-#define vectors_high() (cr_alignment & CR_V)
-#else
-#define vectors_high() (0)
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 7 ||         \
-       (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
-#define sev()  __asm__ __volatile__ ("sev" : : : "memory")
-#define wfe()  __asm__ __volatile__ ("wfe" : : : "memory")
-#define wfi()  __asm__ __volatile__ ("wfi" : : : "memory")
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 7
-#define isb() __asm__ __volatile__ ("isb" : : : "memory")
-#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
-#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
-#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6
-#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
-                                   : : "r" (0) : "memory")
-#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
-                                   : : "r" (0) : "memory")
-#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
-                                   : : "r" (0) : "memory")
-#elif defined(CONFIG_CPU_FA526)
-#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
-                                   : : "r" (0) : "memory")
-#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
-                                   : : "r" (0) : "memory")
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-#else
-#define isb() __asm__ __volatile__ ("" : : : "memory")
-#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
-                                   : : "r" (0) : "memory")
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-#endif
-
-#ifdef CONFIG_ARCH_HAS_BARRIERS
-#include <mach/barriers.h>
-#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
-#define mb()           do { dsb(); outer_sync(); } while (0)
-#define rmb()          dsb()
-#define wmb()          mb()
-#else
-#include <asm/memory.h>
-#define mb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#define rmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#define wmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#endif
-
-#ifndef CONFIG_SMP
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#else
-#define smp_mb()       dmb()
-#define smp_rmb()      dmb()
-#define smp_wmb()      dmb()
-#endif
-
-#define read_barrier_depends()         do { } while(0)
-#define smp_read_barrier_depends()     do { } while(0)
-
-#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
-extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
-extern unsigned long cr_alignment;     /* defined in entry-armv.S */
-
-static inline unsigned int get_cr(void)
-{
-       unsigned int val;
-       asm("mrc p15, 0, %0, c1, c0, 0  @ get CR" : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_cr(unsigned int val)
-{
-       asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
-         : : "r" (val) : "cc");
-       isb();
-}
-
-#ifndef CONFIG_SMP
-extern void adjust_cr(unsigned long mask, unsigned long set);
-#endif
-
-#define CPACC_FULL(n)          (3 << (n * 2))
-#define CPACC_SVC(n)           (1 << (n * 2))
-#define CPACC_DISABLE(n)       (0 << (n * 2))
-
-static inline unsigned int get_copro_access(void)
-{
-       unsigned int val;
-       asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access"
-         : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_copro_access(unsigned int val)
-{
-       asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
-         : : "r" (val) : "cc");
-       isb();
-}
-
-/*
- * switch_mm() may do a full cache flush over the context switch,
- * so enable interrupts over the context switch to avoid high
- * latency.
- */
-#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.  schedule() itself
- * contains the memory barrier to tell GCC not to cache `current'.
- */
-extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
-
-#define switch_to(prev,next,last)                                      \
-do {                                                                   \
-       last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
-} while (0)
-
-#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
-/*
- * On the StrongARM, "swp" is terminally broken since it bypasses the
- * cache totally.  This means that the cache becomes inconsistent, and,
- * since we use normal loads/stores as well, this is really bad.
- * Typically, this causes oopsen in filp_close, but could have other,
- * more disastrous effects.  There are two work-arounds:
- *  1. Disable interrupts and emulate the atomic swap
- *  2. Clean the cache, perform atomic swap, flush the cache
- *
- * We choose (1) since its the "easiest" to achieve here and is not
- * dependent on the processor type.
- *
- * NOTE that this solution won't work on an SMP system, so explcitly
- * forbid it here.
- */
-#define swp_is_buggy
-#endif
-
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
-       extern void __bad_xchg(volatile void *, int);
-       unsigned long ret;
-#ifdef swp_is_buggy
-       unsigned long flags;
-#endif
-#if __LINUX_ARM_ARCH__ >= 6
-       unsigned int tmp;
-#endif
-
-       smp_mb();
-
-       switch (size) {
-#if __LINUX_ARM_ARCH__ >= 6
-       case 1:
-               asm volatile("@ __xchg1\n"
-               "1:     ldrexb  %0, [%3]\n"
-               "       strexb  %1, %2, [%3]\n"
-               "       teq     %1, #0\n"
-               "       bne     1b"
-                       : "=&r" (ret), "=&r" (tmp)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       case 4:
-               asm volatile("@ __xchg4\n"
-               "1:     ldrex   %0, [%3]\n"
-               "       strex   %1, %2, [%3]\n"
-               "       teq     %1, #0\n"
-               "       bne     1b"
-                       : "=&r" (ret), "=&r" (tmp)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-#elif defined(swp_is_buggy)
-#ifdef CONFIG_SMP
-#error SMP is not supported on this platform
-#endif
-       case 1:
-               raw_local_irq_save(flags);
-               ret = *(volatile unsigned char *)ptr;
-               *(volatile unsigned char *)ptr = x;
-               raw_local_irq_restore(flags);
-               break;
-
-       case 4:
-               raw_local_irq_save(flags);
-               ret = *(volatile unsigned long *)ptr;
-               *(volatile unsigned long *)ptr = x;
-               raw_local_irq_restore(flags);
-               break;
-#else
-       case 1:
-               asm volatile("@ __xchg1\n"
-               "       swpb    %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       case 4:
-               asm volatile("@ __xchg4\n"
-               "       swp     %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-#endif
-       default:
-               __bad_xchg(ptr, size), ret = 0;
-               break;
-       }
-       smp_mb();
-
-       return ret;
-}
-
-extern void disable_hlt(void);
-extern void enable_hlt(void);
-
-void cpu_idle_wait(void);
-
-#include <asm-generic/cmpxchg-local.h>
-
-#if __LINUX_ARM_ARCH__ < 6
-/* min ARCH < ARMv6 */
-
-#ifdef CONFIG_SMP
-#error "SMP is not supported on this platform"
-#endif
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#else  /* min ARCH >= ARMv6 */
-
-extern void __bad_cmpxchg(volatile void *ptr, int size);
-
-/*
- * cmpxchg only support 32-bits operands on ARMv6.
- */
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       unsigned long oldval, res;
-
-       switch (size) {
-#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
-       case 1:
-               do {
-                       asm volatile("@ __cmpxchg1\n"
-                       "       ldrexb  %1, [%2]\n"
-                       "       mov     %0, #0\n"
-                       "       teq     %1, %3\n"
-                       "       strexbeq %0, %4, [%2]\n"
-                               : "=&r" (res), "=&r" (oldval)
-                               : "r" (ptr), "Ir" (old), "r" (new)
-                               : "memory", "cc");
-               } while (res);
-               break;
-       case 2:
-               do {
-                       asm volatile("@ __cmpxchg1\n"
-                       "       ldrexh  %1, [%2]\n"
-                       "       mov     %0, #0\n"
-                       "       teq     %1, %3\n"
-                       "       strexheq %0, %4, [%2]\n"
-                               : "=&r" (res), "=&r" (oldval)
-                               : "r" (ptr), "Ir" (old), "r" (new)
-                               : "memory", "cc");
-               } while (res);
-               break;
-#endif
-       case 4:
-               do {
-                       asm volatile("@ __cmpxchg4\n"
-                       "       ldrex   %1, [%2]\n"
-                       "       mov     %0, #0\n"
-                       "       teq     %1, %3\n"
-                       "       strexeq %0, %4, [%2]\n"
-                               : "=&r" (res), "=&r" (oldval)
-                               : "r" (ptr), "Ir" (old), "r" (new)
-                               : "memory", "cc");
-               } while (res);
-               break;
-       default:
-               __bad_cmpxchg(ptr, size);
-               oldval = 0;
-       }
-
-       return oldval;
-}
-
-static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
-                                        unsigned long new, int size)
-{
-       unsigned long ret;
-
-       smp_mb();
-       ret = __cmpxchg(ptr, old, new, size);
-       smp_mb();
-
-       return ret;
-}
-
-#define cmpxchg(ptr,o,n)                                               \
-       ((__typeof__(*(ptr)))__cmpxchg_mb((ptr),                        \
-                                         (unsigned long)(o),           \
-                                         (unsigned long)(n),           \
-                                         sizeof(*(ptr))))
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                           unsigned long old,
-                                           unsigned long new, int size)
-{
-       unsigned long ret;
-
-       switch (size) {
-#ifdef CONFIG_CPU_V6   /* min ARCH == ARMv6 */
-       case 1:
-       case 2:
-               ret = __cmpxchg_local_generic(ptr, old, new, size);
-               break;
-#endif
-       default:
-               ret = __cmpxchg(ptr, old, new, size);
-       }
-
-       return ret;
-}
-
-#define cmpxchg_local(ptr,o,n)                                         \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr),                     \
-                                      (unsigned long)(o),              \
-                                      (unsigned long)(n),              \
-                                      sizeof(*(ptr))))
-
-#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
-
-/*
- * Note : ARMv7-M (currently unsupported by Linux) does not support
- * ldrexd/strexd. If ARMv7-M is ever supported by the Linux kernel, it should
- * not be allowed to use __cmpxchg64.
- */
-static inline unsigned long long __cmpxchg64(volatile void *ptr,
-                                            unsigned long long old,
-                                            unsigned long long new)
-{
-       register unsigned long long oldval asm("r0");
-       register unsigned long long __old asm("r2") = old;
-       register unsigned long long __new asm("r4") = new;
-       unsigned long res;
-
-       do {
-               asm volatile(
-               "       @ __cmpxchg8\n"
-               "       ldrexd  %1, %H1, [%2]\n"
-               "       mov     %0, #0\n"
-               "       teq     %1, %3\n"
-               "       teqeq   %H1, %H3\n"
-               "       strexdeq %0, %4, %H4, [%2]\n"
-                       : "=&r" (res), "=&r" (oldval)
-                       : "r" (ptr), "Ir" (__old), "r" (__new)
-                       : "memory", "cc");
-       } while (res);
-
-       return oldval;
-}
-
-static inline unsigned long long __cmpxchg64_mb(volatile void *ptr,
-                                               unsigned long long old,
-                                               unsigned long long new)
-{
-       unsigned long long ret;
-
-       smp_mb();
-       ret = __cmpxchg64(ptr, old, new);
-       smp_mb();
-
-       return ret;
-}
-
-#define cmpxchg64(ptr,o,n)                                             \
-       ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),                      \
-                                           (unsigned long long)(o),    \
-                                           (unsigned long long)(n)))
-
-#define cmpxchg64_local(ptr,o,n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg64((ptr),                         \
-                                        (unsigned long long)(o),       \
-                                        (unsigned long long)(n)))
-
-#else /* min ARCH = ARMv6 */
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif
-
-#endif /* __LINUX_ARM_ARCH__ >= 6 */
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif
+/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
+#include <asm/barrier.h>
+#include <asm/compiler.h>
+#include <asm/cmpxchg.h>
+#include <asm/exec.h>
+#include <asm/switch_to.h>
+#include <asm/system_info.h>
+#include <asm/system_misc.h>
diff --git a/arch/arm/include/asm/system_info.h b/arch/arm/include/asm/system_info.h
new file mode 100644 (file)
index 0000000..dfd386d
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __ASM_ARM_SYSTEM_INFO_H
+#define __ASM_ARM_SYSTEM_INFO_H
+
+#define CPU_ARCH_UNKNOWN       0
+#define CPU_ARCH_ARMv3         1
+#define CPU_ARCH_ARMv4         2
+#define CPU_ARCH_ARMv4T                3
+#define CPU_ARCH_ARMv5         4
+#define CPU_ARCH_ARMv5T                5
+#define CPU_ARCH_ARMv5TE       6
+#define CPU_ARCH_ARMv5TEJ      7
+#define CPU_ARCH_ARMv6         8
+#define CPU_ARCH_ARMv7         9
+
+#ifndef __ASSEMBLY__
+
+/* information about the system we're running on */
+extern unsigned int system_rev;
+extern unsigned int system_serial_low;
+extern unsigned int system_serial_high;
+extern unsigned int mem_fclk_21285;
+
+extern int __pure cpu_architecture(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __ASM_ARM_SYSTEM_INFO_H */
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
new file mode 100644 (file)
index 0000000..5a85f14
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASM_ARM_SYSTEM_MISC_H
+#define __ASM_ARM_SYSTEM_MISC_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+
+extern void cpu_init(void);
+
+void soft_restart(unsigned long);
+extern void (*arm_pm_restart)(char str, const char *cmd);
+extern void (*arm_pm_idle)(void);
+
+#define UDBG_UNDEFINED (1 << 0)
+#define UDBG_SYSCALL   (1 << 1)
+#define UDBG_BADABORT  (1 << 2)
+#define UDBG_SEGV      (1 << 3)
+#define UDBG_BUS       (1 << 4)
+
+extern unsigned int user_debug;
+
+extern void disable_hlt(void);
+extern void enable_hlt(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __ASM_ARM_SYSTEM_MISC_H */
index 02b2f82039828bb0d4b016e41882c3071b686b93..85fe61e7320265e6932e8659d95c57c7712ad04d 100644 (file)
@@ -318,6 +318,21 @@ extern struct cpu_tlb_fns cpu_tlb;
 
 #define tlb_flag(f)    ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
 
+#define __tlb_op(f, insnarg, arg)                                      \
+       do {                                                            \
+               if (always_tlb_flags & (f))                             \
+                       asm("mcr " insnarg                              \
+                           : : "r" (arg) : "cc");                      \
+               else if (possible_tlb_flags & (f))                      \
+                       asm("tst %1, %2\n\t"                            \
+                           "mcrne " insnarg                            \
+                           : : "r" (arg), "r" (__tlb_flag), "Ir" (f)   \
+                           : "cc");                                    \
+       } while (0)
+
+#define tlb_op(f, regs, arg)   __tlb_op(f, "p15, 0, %0, " regs, arg)
+#define tlb_l2_op(f, regs, arg)        __tlb_op(f, "p15, 1, %0, " regs, arg)
+
 static inline void local_flush_tlb_all(void)
 {
        const int zero = 0;
@@ -326,16 +341,11 @@ static inline void local_flush_tlb_all(void)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (tlb_flag(TLB_V3_FULL))
-               asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL))
-               asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL))
-               asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
-               asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V7_UIS_FULL))
-               asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
+       tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
+       tlb_op(TLB_V4_U_FULL | TLB_V6_U_FULL, "c8, c7, 0", zero);
+       tlb_op(TLB_V4_D_FULL | TLB_V6_D_FULL, "c8, c6, 0", zero);
+       tlb_op(TLB_V4_I_FULL | TLB_V6_I_FULL, "c8, c5, 0", zero);
+       tlb_op(TLB_V7_UIS_FULL, "c8, c3, 0", zero);
 
        if (tlb_flag(TLB_BARRIER)) {
                dsb();
@@ -352,29 +362,23 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
-               if (tlb_flag(TLB_V3_FULL))
-                       asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
-               if (tlb_flag(TLB_V4_U_FULL))
-                       asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
-               if (tlb_flag(TLB_V4_D_FULL))
-                       asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
-               if (tlb_flag(TLB_V4_I_FULL))
-                       asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+       if (possible_tlb_flags & (TLB_V3_FULL|TLB_V4_U_FULL|TLB_V4_D_FULL|TLB_V4_I_FULL)) {
+               if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
+                       tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
+                       tlb_op(TLB_V4_U_FULL, "c8, c7, 0", zero);
+                       tlb_op(TLB_V4_D_FULL, "c8, c6, 0", zero);
+                       tlb_op(TLB_V4_I_FULL, "c8, c5, 0", zero);
+               }
+               put_cpu();
        }
-       put_cpu();
-
-       if (tlb_flag(TLB_V6_U_ASID))
-               asm("mcr p15, 0, %0, c8, c7, 2" : : "r" (asid) : "cc");
-       if (tlb_flag(TLB_V6_D_ASID))
-               asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
-       if (tlb_flag(TLB_V6_I_ASID))
-               asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
-       if (tlb_flag(TLB_V7_UIS_ASID))
+
+       tlb_op(TLB_V6_U_ASID, "c8, c7, 2", asid);
+       tlb_op(TLB_V6_D_ASID, "c8, c6, 2", asid);
+       tlb_op(TLB_V6_I_ASID, "c8, c5, 2", asid);
 #ifdef CONFIG_ARM_ERRATA_720789
-               asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
+       tlb_op(TLB_V7_UIS_ASID, "c8, c3, 0", zero);
 #else
-               asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
+       tlb_op(TLB_V7_UIS_ASID, "c8, c3, 2", asid);
 #endif
 
        if (tlb_flag(TLB_BARRIER))
@@ -392,30 +396,23 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
-               if (tlb_flag(TLB_V3_PAGE))
-                       asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (uaddr) : "cc");
-               if (tlb_flag(TLB_V4_U_PAGE))
-                       asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
-               if (tlb_flag(TLB_V4_D_PAGE))
-                       asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
-               if (tlb_flag(TLB_V4_I_PAGE))
-                       asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
+       if (possible_tlb_flags & (TLB_V3_PAGE|TLB_V4_U_PAGE|TLB_V4_D_PAGE|TLB_V4_I_PAGE|TLB_V4_I_FULL) &&
+           cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
+               tlb_op(TLB_V3_PAGE, "c6, c0, 0", uaddr);
+               tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", uaddr);
+               tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", uaddr);
+               tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", uaddr);
                if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
                        asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
        }
 
-       if (tlb_flag(TLB_V6_U_PAGE))
-               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
-       if (tlb_flag(TLB_V6_D_PAGE))
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
-       if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
-       if (tlb_flag(TLB_V7_UIS_PAGE))
+       tlb_op(TLB_V6_U_PAGE, "c8, c7, 1", uaddr);
+       tlb_op(TLB_V6_D_PAGE, "c8, c6, 1", uaddr);
+       tlb_op(TLB_V6_I_PAGE, "c8, c5, 1", uaddr);
 #ifdef CONFIG_ARM_ERRATA_720789
-               asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc");
+       tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 3", uaddr & PAGE_MASK);
 #else
-               asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
+       tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 1", uaddr);
 #endif
 
        if (tlb_flag(TLB_BARRIER))
@@ -432,25 +429,17 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (tlb_flag(TLB_V3_PAGE))
-               asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V4_U_PAGE))
-               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V4_D_PAGE))
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V4_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
+       tlb_op(TLB_V3_PAGE, "c6, c0, 0", kaddr);
+       tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", kaddr);
+       tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", kaddr);
+       tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", kaddr);
        if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
                asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 
-       if (tlb_flag(TLB_V6_U_PAGE))
-               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V6_D_PAGE))
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V7_UIS_PAGE))
-               asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
+       tlb_op(TLB_V6_U_PAGE, "c8, c7, 1", kaddr);
+       tlb_op(TLB_V6_D_PAGE, "c8, c6, 1", kaddr);
+       tlb_op(TLB_V6_I_PAGE, "c8, c5, 1", kaddr);
+       tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 1", kaddr);
 
        if (tlb_flag(TLB_BARRIER)) {
                dsb();
@@ -475,13 +464,8 @@ static inline void flush_pmd_entry(void *pmd)
 {
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
-       if (tlb_flag(TLB_DCLEAN))
-               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd) : "cc");
-
-       if (tlb_flag(TLB_L2CLEAN_FR))
-               asm("mcr        p15, 1, %0, c15, c9, 1  @ L2 flush_pmd"
-                       : : "r" (pmd) : "cc");
+       tlb_op(TLB_DCLEAN, "c7, c10, 1  @ flush_pmd", pmd);
+       tlb_l2_op(TLB_L2CLEAN_FR, "c15, c9, 1  @ L2 flush_pmd", pmd);
 
        if (tlb_flag(TLB_WB))
                dsb();
@@ -491,15 +475,11 @@ static inline void clean_pmd_entry(void *pmd)
 {
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
-       if (tlb_flag(TLB_DCLEAN))
-               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd) : "cc");
-
-       if (tlb_flag(TLB_L2CLEAN_FR))
-               asm("mcr        p15, 1, %0, c15, c9, 1  @ L2 flush_pmd"
-                       : : "r" (pmd) : "cc");
+       tlb_op(TLB_DCLEAN, "c7, c10, 1  @ flush_pmd", pmd);
+       tlb_l2_op(TLB_L2CLEAN_FR, "c15, c9, 1  @ L2 flush_pmd", pmd);
 }
 
+#undef tlb_op
 #undef tlb_flag
 #undef always_tlb_flags
 #undef possible_tlb_flags
index 5b29a66736250e71d9a4ee24cfb9e0cd341ea14f..f555bb3664dcaa2dbee6ab4e1f486d24e360ba8f 100644 (file)
@@ -46,7 +46,7 @@ static inline int in_exception_text(unsigned long ptr)
        return in ? : __in_irqentry_text(ptr);
 }
 
-extern void __init early_trap_init(void);
+extern void __init early_trap_init(void *);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
 
index 2958976d867b4b9795a090cee9a6b9cacb646631..71f6536d17ac01d53f638c47edbc4a5589f95838 100644 (file)
@@ -16,8 +16,8 @@
 #include <asm/errno.h>
 #include <asm/memory.h>
 #include <asm/domain.h>
-#include <asm/system.h>
 #include <asm/unified.h>
+#include <asm/compiler.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
index 3a274878412ec7b1728de840469cd1ffc68e3a38..8269d892874232f59f6e49537dc6df49e8c0927b 100644 (file)
@@ -7,6 +7,8 @@ AFLAGS_head.o        := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_patch.o = -pg
 endif
 
 CFLAGS_REMOVE_return_address.o = -pg
@@ -14,8 +16,8 @@ CFLAGS_REMOVE_return_address.o = -pg
 # Object file lists.
 
 obj-y          := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
-                  process.o ptrace.o return_address.o setup.o signal.o \
-                  sys_arm.o stacktrace.o time.o traps.o
+                  process.o ptrace.o return_address.o sched_clock.o \
+                  setup.o signal.o stacktrace.o sys_arm.o time.o traps.o
 
 obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
 
@@ -29,14 +31,14 @@ obj-$(CONFIG_ARTHUR)                += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o isa.o
 obj-$(CONFIG_ARM_CPU_SUSPEND)  += sleep.o suspend.o
-obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
 obj-$(CONFIG_SMP)              += smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)     += smp_scu.o
 obj-$(CONFIG_HAVE_ARM_TWD)     += smp_twd.o
-obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
-obj-$(CONFIG_FUNCTION_GRAPH_TRACER)    += ftrace.o
+obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o insn.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER)    += ftrace.o insn.o
+obj-$(CONFIG_JUMP_LABEL)       += jump_label.o insn.o patch.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES)          += kprobes.o kprobes-common.o
+obj-$(CONFIG_KPROBES)          += kprobes.o kprobes-common.o patch.o
 ifdef CONFIG_THUMB2_KERNEL
 obj-$(CONFIG_KPROBES)          += kprobes-thumb.o
 else
index 5b0bce61eb6922049fb509169938209b3755d038..b57c75e0b01f975defe734de3cce7c6ecfb34dda 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <asm/checksum.h>
-#include <asm/system.h>
 #include <asm/ftrace.h>
 
 /*
index 204e2160cfccbdd5fa88a00285086d73a522ebcb..c45522c36787fd3c62240076337a7cda2fee5489 100644 (file)
@@ -10,6 +10,7 @@
  *  32-bit debugging code
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
                .text
 
 
 #endif /* CONFIG_CPU_V6 */
 
-#else
+#elif !defined(CONFIG_DEBUG_SEMIHOSTING)
 #include <mach/debug-macro.S>
 #endif /* CONFIG_DEBUG_ICEDCC */
 
@@ -155,6 +156,8 @@ hexbuf:             .space 16
 
                .ltorg
 
+#ifndef CONFIG_DEBUG_SEMIHOSTING
+
 ENTRY(printascii)
                addruart_current r3, r1, r2
                b       2f
@@ -177,3 +180,24 @@ ENTRY(printch)
                mov     r0, #0
                b       1b
 ENDPROC(printch)
+
+#else
+
+ENTRY(printascii)
+               mov     r1, r0
+               mov     r0, #0x04               @ SYS_WRITE0
+       ARM(    svc     #0x123456       )
+       THUMB(  svc     #0xab           )
+               mov     pc, lr
+ENDPROC(printascii)
+
+ENTRY(printch)
+               adr     r1, hexbuf
+               strb    r0, [r1]
+               mov     r0, #0x03               @ SYS_WRITEC
+       ARM(    svc     #0x123456       )
+       THUMB(  svc     #0xab           )
+               mov     pc, lr
+ENDPROC(printch)
+
+#endif
index ddba41d1fcf148ab1a3bde141dff1087dcb6919d..d0d1e83150c9553619c4a7f6c76605504d8765bc 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
+#include <asm/system_info.h>
 
 int elf_check_arch(const struct elf32_hdr *x)
 {
index 22f0ed324f370b904279a349167ceba3a5ec8c5a..7fd3ad048da9b7318ed516edc81ae67cb95e0c52 100644 (file)
@@ -15,6 +15,7 @@
  *  that causes it to save wrong values...  Be aware!
  */
 
+#include <asm/assembler.h>
 #include <asm/memory.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
@@ -26,7 +27,7 @@
 #include <asm/unwind.h>
 #include <asm/unistd.h>
 #include <asm/tls.h>
-#include <asm/system.h>
+#include <asm/system_info.h>
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
index 4c164ece5891cfba0bd5e346a4fc51565f92d94b..c32f8456aa094115b8c28a92df83fc643a15188c 100644 (file)
@@ -42,9 +42,9 @@
 #include <linux/seq_file.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/fiq.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 static unsigned long no_fiq_insn;
index c0062ad1e847b5a1ab68a21a8ed3f4d37eb9ce2a..df0bf0c8cb790a5ee501c55a204a45ddbcb48aab 100644 (file)
 #include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
+#include <asm/opcodes.h>
 #include <asm/ftrace.h>
 
+#include "insn.h"
+
 #ifdef CONFIG_THUMB2_KERNEL
-#define        NOP             0xeb04f85d      /* pop.w {lr} */
+#define        NOP             0xf85deb04      /* pop.w {lr} */
 #else
 #define        NOP             0xe8bd4000      /* pop {lr} */
 #endif
@@ -60,76 +63,31 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
 }
 #endif
 
-#ifdef CONFIG_THUMB2_KERNEL
-static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
-                                      bool link)
-{
-       unsigned long s, j1, j2, i1, i2, imm10, imm11;
-       unsigned long first, second;
-       long offset;
-
-       offset = (long)addr - (long)(pc + 4);
-       if (offset < -16777216 || offset > 16777214) {
-               WARN_ON_ONCE(1);
-               return 0;
-       }
-
-       s       = (offset >> 24) & 0x1;
-       i1      = (offset >> 23) & 0x1;
-       i2      = (offset >> 22) & 0x1;
-       imm10   = (offset >> 12) & 0x3ff;
-       imm11   = (offset >>  1) & 0x7ff;
-
-       j1 = (!i1) ^ s;
-       j2 = (!i2) ^ s;
-
-       first = 0xf000 | (s << 10) | imm10;
-       second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
-       if (link)
-               second |= 1 << 14;
-
-       return (second << 16) | first;
-}
-#else
-static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
-                                      bool link)
-{
-       unsigned long opcode = 0xea000000;
-       long offset;
-
-       if (link)
-               opcode |= 1 << 24;
-
-       offset = (long)addr - (long)(pc + 8);
-       if (unlikely(offset < -33554432 || offset > 33554428)) {
-               /* Can't generate branches that far (from ARM ARM). Ftrace
-                * doesn't generate branches outside of kernel text.
-                */
-               WARN_ON_ONCE(1);
-               return 0;
-       }
-
-       offset = (offset >> 2) & 0x00ffffff;
-
-       return opcode | offset;
-}
-#endif
-
 static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
 {
-       return ftrace_gen_branch(pc, addr, true);
+       return arm_gen_branch_link(pc, addr);
 }
 
 static int ftrace_modify_code(unsigned long pc, unsigned long old,
-                             unsigned long new)
+                             unsigned long new, bool validate)
 {
        unsigned long replaced;
 
-       if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
-               return -EFAULT;
+       if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) {
+               old = __opcode_to_mem_thumb32(old);
+               new = __opcode_to_mem_thumb32(new);
+       } else {
+               old = __opcode_to_mem_arm(old);
+               new = __opcode_to_mem_arm(new);
+       }
 
-       if (replaced != old)
-               return -EINVAL;
+       if (validate) {
+               if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+                       return -EFAULT;
+
+               if (replaced != old)
+                       return -EINVAL;
+       }
 
        if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
                return -EPERM;
@@ -141,23 +99,21 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-       unsigned long pc, old;
+       unsigned long pc;
        unsigned long new;
        int ret;
 
        pc = (unsigned long)&ftrace_call;
-       memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
        new = ftrace_call_replace(pc, (unsigned long)func);
 
-       ret = ftrace_modify_code(pc, old, new);
+       ret = ftrace_modify_code(pc, 0, new, false);
 
 #ifdef CONFIG_OLD_MCOUNT
        if (!ret) {
                pc = (unsigned long)&ftrace_call_old;
-               memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
                new = ftrace_call_replace(pc, (unsigned long)func);
 
-               ret = ftrace_modify_code(pc, old, new);
+               ret = ftrace_modify_code(pc, 0, new, false);
        }
 #endif
 
@@ -172,7 +128,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
        old = ftrace_nop_replace(rec);
        new = ftrace_call_replace(ip, adjust_address(rec, addr));
 
-       return ftrace_modify_code(rec->ip, old, new);
+       return ftrace_modify_code(rec->ip, old, new, true);
 }
 
 int ftrace_make_nop(struct module *mod,
@@ -185,7 +141,7 @@ int ftrace_make_nop(struct module *mod,
 
        old = ftrace_call_replace(ip, adjust_address(rec, addr));
        new = ftrace_nop_replace(rec);
-       ret = ftrace_modify_code(ip, old, new);
+       ret = ftrace_modify_code(ip, old, new, true);
 
 #ifdef CONFIG_OLD_MCOUNT
        if (ret == -EINVAL && addr == MCOUNT_ADDR) {
@@ -193,7 +149,7 @@ int ftrace_make_nop(struct module *mod,
 
                old = ftrace_call_replace(ip, adjust_address(rec, addr));
                new = ftrace_nop_replace(rec);
-               ret = ftrace_modify_code(ip, old, new);
+               ret = ftrace_modify_code(ip, old, new, true);
        }
 #endif
 
@@ -249,12 +205,12 @@ static int __ftrace_modify_caller(unsigned long *callsite,
 {
        unsigned long caller_fn = (unsigned long) func;
        unsigned long pc = (unsigned long) callsite;
-       unsigned long branch = ftrace_gen_branch(pc, caller_fn, false);
+       unsigned long branch = arm_gen_branch(pc, caller_fn);
        unsigned long nop = 0xe1a00000; /* mov r0, r0 */
        unsigned long old = enable ? nop : branch;
        unsigned long new = enable ? branch : nop;
 
-       return ftrace_modify_code(pc, old, new);
+       return ftrace_modify_code(pc, old, new, true);
 }
 
 static int ftrace_modify_graph_caller(bool enable)
index d46f25968bec2ce04143daa785de6a63cf4b635b..278cfc144f448012100d594c0f81041cdfbf474c 100644 (file)
@@ -17,8 +17,8 @@
 #include <asm/assembler.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
+#include <asm/cp15.h>
 #include <asm/thread_info.h>
-#include <asm/system.h>
 
 /*
  * Kernel startup entry point.
index 6d579114406673fd1b97c09f0cdcbb7263b044da..3bf0c7f8b043c52b4e616397cc768541a6009a89 100644 (file)
 #include <linux/init.h>
 
 #include <asm/assembler.h>
+#include <asm/cp15.h>
 #include <asm/domain.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/memory.h>
 #include <asm/thread_info.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 
 #ifdef CONFIG_DEBUG_LL
@@ -265,7 +265,7 @@ __create_page_tables:
        str     r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
-#ifndef CONFIG_DEBUG_ICEDCC
+#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
        /*
         * Map in IO space for serial debugging.
         * This allows debug messages to be output
@@ -297,10 +297,10 @@ __create_page_tables:
        cmp     r0, r6
        blo     1b
 
-#else /* CONFIG_DEBUG_ICEDCC */
-       /* we don't need any serial debugging mappings for ICEDCC */
+#else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */
+       /* we don't need any serial debugging mappings */
        ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
-#endif /* !CONFIG_DEBUG_ICEDCC */
+#endif
 
 #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
        /*
index d6a95ef9131d5a567b257c056b6f932ce7b0ac23..ba386bd94107642d9819a7d8bafb7ba04e92b83f 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/current.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/kdebug.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 /* Breakpoint currently in use for each BRP. */
diff --git a/arch/arm/kernel/insn.c b/arch/arm/kernel/insn.c
new file mode 100644 (file)
index 0000000..ab312e5
--- /dev/null
@@ -0,0 +1,61 @@
+#include <linux/kernel.h>
+#include <asm/opcodes.h>
+
+static unsigned long
+__arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link)
+{
+       unsigned long s, j1, j2, i1, i2, imm10, imm11;
+       unsigned long first, second;
+       long offset;
+
+       offset = (long)addr - (long)(pc + 4);
+       if (offset < -16777216 || offset > 16777214) {
+               WARN_ON_ONCE(1);
+               return 0;
+       }
+
+       s       = (offset >> 24) & 0x1;
+       i1      = (offset >> 23) & 0x1;
+       i2      = (offset >> 22) & 0x1;
+       imm10   = (offset >> 12) & 0x3ff;
+       imm11   = (offset >>  1) & 0x7ff;
+
+       j1 = (!i1) ^ s;
+       j2 = (!i2) ^ s;
+
+       first = 0xf000 | (s << 10) | imm10;
+       second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
+       if (link)
+               second |= 1 << 14;
+
+       return __opcode_thumb32_compose(first, second);
+}
+
+static unsigned long
+__arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link)
+{
+       unsigned long opcode = 0xea000000;
+       long offset;
+
+       if (link)
+               opcode |= 1 << 24;
+
+       offset = (long)addr - (long)(pc + 8);
+       if (unlikely(offset < -33554432 || offset > 33554428)) {
+               WARN_ON_ONCE(1);
+               return 0;
+       }
+
+       offset = (offset >> 2) & 0x00ffffff;
+
+       return opcode | offset;
+}
+
+unsigned long
+__arm_gen_branch(unsigned long pc, unsigned long addr, bool link)
+{
+       if (IS_ENABLED(CONFIG_THUMB2_KERNEL))
+               return __arm_gen_branch_thumb2(pc, addr, link);
+       else
+               return __arm_gen_branch_arm(pc, addr, link);
+}
diff --git a/arch/arm/kernel/insn.h b/arch/arm/kernel/insn.h
new file mode 100644 (file)
index 0000000..e96065d
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASM_ARM_INSN_H
+#define __ASM_ARM_INSN_H
+
+static inline unsigned long
+arm_gen_nop(void)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+       return 0xf3af8000; /* nop.w */
+#else
+       return 0xe1a00000; /* mov r0, r0 */
+#endif
+}
+
+unsigned long
+__arm_gen_branch(unsigned long pc, unsigned long addr, bool link);
+
+static inline unsigned long
+arm_gen_branch(unsigned long pc, unsigned long addr)
+{
+       return __arm_gen_branch(pc, addr, false);
+}
+
+static inline unsigned long
+arm_gen_branch_link(unsigned long pc, unsigned long addr)
+{
+       return __arm_gen_branch(pc, addr, true);
+}
+
+#endif
index 3efd82cc95f06a8196b6a20e8c9fa65121d66009..71ccdbfed66276f2c76db1b683da17cab392f0ad 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/proc_fs.h>
 
 #include <asm/exception.h>
-#include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
@@ -181,10 +180,7 @@ void migrate_irqs(void)
        local_irq_save(flags);
 
        for_each_irq_desc(i, desc) {
-               bool affinity_broken = false;
-
-               if (!desc)
-                       continue;
+               bool affinity_broken;
 
                raw_spin_lock(&desc->lock);
                affinity_broken = migrate_one_irq(desc);
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..4ce4f78
--- /dev/null
@@ -0,0 +1,39 @@
+#include <linux/kernel.h>
+#include <linux/jump_label.h>
+
+#include "insn.h"
+#include "patch.h"
+
+#ifdef HAVE_JUMP_LABEL
+
+static void __arch_jump_label_transform(struct jump_entry *entry,
+                                       enum jump_label_type type,
+                                       bool is_static)
+{
+       void *addr = (void *)entry->code;
+       unsigned int insn;
+
+       if (type == JUMP_LABEL_ENABLE)
+               insn = arm_gen_branch(entry->code, entry->target);
+       else
+               insn = arm_gen_nop();
+
+       if (is_static)
+               __patch_text(addr, insn);
+       else
+               patch_text(addr, insn);
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
+{
+       __arch_jump_label_transform(entry, type, false);
+}
+
+void arch_jump_label_transform_static(struct jump_entry *entry,
+                                     enum jump_label_type type)
+{
+       __arch_jump_label_transform(entry, type, true);
+}
+
+#endif
index a5394fb4e4e0808a19e1d6d8a5ed5d42a4d0235e..18a76282970e6dfaa414b6f9ff266553258bd27d 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <asm/system_info.h>
 
 #include "kprobes.h"
 
index 129c1163248bf2acf11133713ec755d7075abea6..ab1869dac97a96a6399964e088f1dc58ff6191e2 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/cacheflush.h>
 
 #include "kprobes.h"
+#include "patch.h"
 
 #define MIN_STACK_SIZE(addr)                           \
        min((unsigned long)MAX_STACK_SIZE,              \
@@ -103,57 +104,33 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        return 0;
 }
 
-#ifdef CONFIG_THUMB2_KERNEL
-
-/*
- * For a 32-bit Thumb breakpoint spanning two memory words we need to take
- * special precautions to insert the breakpoint atomically, especially on SMP
- * systems. This is achieved by calling this arming function using stop_machine.
- */
-static int __kprobes set_t32_breakpoint(void *addr)
-{
-       ((u16 *)addr)[0] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION >> 16;
-       ((u16 *)addr)[1] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION & 0xffff;
-       flush_insns(addr, 2*sizeof(u16));
-       return 0;
-}
-
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-       uintptr_t addr = (uintptr_t)p->addr & ~1; /* Remove any Thumb flag */
-
-       if (!is_wide_instruction(p->opcode)) {
-               *(u16 *)addr = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
-               flush_insns(addr, sizeof(u16));
-       } else if (addr & 2) {
-               /* A 32-bit instruction spanning two words needs special care */
-               stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
+       unsigned int brkp;
+       void *addr;
+
+       if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) {
+               /* Remove any Thumb flag */
+               addr = (void *)((uintptr_t)p->addr & ~1);
+
+               if (is_wide_instruction(p->opcode))
+                       brkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
+               else
+                       brkp = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
        } else {
-               /* Word aligned 32-bit instruction can be written atomically */
-               u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
-#ifndef __ARMEB__ /* Swap halfwords for little-endian */
-               bkp = (bkp >> 16) | (bkp << 16);
-#endif
-               *(u32 *)addr = bkp;
-               flush_insns(addr, sizeof(u32));
-       }
-}
+               kprobe_opcode_t insn = p->opcode;
 
-#else /* !CONFIG_THUMB2_KERNEL */
+               addr = p->addr;
+               brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
 
-void __kprobes arch_arm_kprobe(struct kprobe *p)
-{
-       kprobe_opcode_t insn = p->opcode;
-       kprobe_opcode_t brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
-       if (insn >= 0xe0000000)
-               brkp |= 0xe0000000;  /* Unconditional instruction */
-       else
-               brkp |= insn & 0xf0000000;  /* Copy condition from insn */
-       *p->addr = brkp;
-       flush_insns(p->addr, sizeof(p->addr[0]));
-}
+               if (insn >= 0xe0000000)
+                       brkp |= 0xe0000000;  /* Unconditional instruction */
+               else
+                       brkp |= insn & 0xf0000000;  /* Copy condition from insn */
+       }
 
-#endif /* !CONFIG_THUMB2_KERNEL */
+       patch_text(addr, brkp);
+}
 
 /*
  * The actual disarming is done here on each CPU and synchronized using
@@ -166,25 +143,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
 int __kprobes __arch_disarm_kprobe(void *p)
 {
        struct kprobe *kp = p;
-#ifdef CONFIG_THUMB2_KERNEL
-       u16 *addr = (u16 *)((uintptr_t)kp->addr & ~1);
-       kprobe_opcode_t insn = kp->opcode;
-       unsigned int len;
+       void *addr = (void *)((uintptr_t)kp->addr & ~1);
 
-       if (is_wide_instruction(insn)) {
-               ((u16 *)addr)[0] = insn>>16;
-               ((u16 *)addr)[1] = insn;
-               len = 2*sizeof(u16);
-       } else {
-               ((u16 *)addr)[0] = insn;
-               len = sizeof(u16);
-       }
-       flush_insns(addr, len);
+       __patch_text(addr, kp->opcode);
 
-#else /* !CONFIG_THUMB2_KERNEL */
-       *kp->addr = kp->opcode;
-       flush_insns(kp->addr, sizeof(kp->addr[0]));
-#endif
        return 0;
 }
 
index 764bd456d84f10580b142f0fc44e8a47c97a5a68..dfcdb9f7c1261143f93c31846ed372269a4b4783 100644 (file)
@@ -7,12 +7,13 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
@@ -53,6 +54,29 @@ void machine_crash_nonpanic_core(void *unused)
                cpu_relax();
 }
 
+static void machine_kexec_mask_interrupts(void)
+{
+       unsigned int i;
+       struct irq_desc *desc;
+
+       for_each_irq_desc(i, desc) {
+               struct irq_chip *chip;
+
+               chip = irq_desc_get_chip(desc);
+               if (!chip)
+                       continue;
+
+               if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
+                       chip->irq_eoi(&desc->irq_data);
+
+               if (chip->irq_mask)
+                       chip->irq_mask(&desc->irq_data);
+
+               if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
+                       chip->irq_disable(&desc->irq_data);
+       }
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
        unsigned long msecs;
@@ -70,6 +94,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
                printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
 
        crash_save_cpu(regs, smp_processor_id());
+       machine_kexec_mask_interrupts();
 
        printk(KERN_INFO "Loading crashdump kernel...\n");
 }
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c
new file mode 100644 (file)
index 0000000..07314af
--- /dev/null
@@ -0,0 +1,75 @@
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/stop_machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/opcodes.h>
+
+#include "patch.h"
+
+struct patch {
+       void *addr;
+       unsigned int insn;
+};
+
+void __kprobes __patch_text(void *addr, unsigned int insn)
+{
+       bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL);
+       int size;
+
+       if (thumb2 && __opcode_is_thumb16(insn)) {
+               *(u16 *)addr = __opcode_to_mem_thumb16(insn);
+               size = sizeof(u16);
+       } else if (thumb2 && ((uintptr_t)addr & 2)) {
+               u16 first = __opcode_thumb32_first(insn);
+               u16 second = __opcode_thumb32_second(insn);
+               u16 *addrh = addr;
+
+               addrh[0] = __opcode_to_mem_thumb16(first);
+               addrh[1] = __opcode_to_mem_thumb16(second);
+
+               size = sizeof(u32);
+       } else {
+               if (thumb2)
+                       insn = __opcode_to_mem_thumb32(insn);
+               else
+                       insn = __opcode_to_mem_arm(insn);
+
+               *(u32 *)addr = insn;
+               size = sizeof(u32);
+       }
+
+       flush_icache_range((uintptr_t)(addr),
+                          (uintptr_t)(addr) + size);
+}
+
+static int __kprobes patch_text_stop_machine(void *data)
+{
+       struct patch *patch = data;
+
+       __patch_text(patch->addr, patch->insn);
+
+       return 0;
+}
+
+void __kprobes patch_text(void *addr, unsigned int insn)
+{
+       struct patch patch = {
+               .addr = addr,
+               .insn = insn,
+       };
+
+       if (cache_ops_need_broadcast()) {
+               stop_machine(patch_text_stop_machine, &patch, cpu_online_mask);
+       } else {
+               bool straddles_word = IS_ENABLED(CONFIG_THUMB2_KERNEL)
+                                     && __opcode_is_thumb32(insn)
+                                     && ((uintptr_t)addr & 2);
+
+               if (straddles_word)
+                       stop_machine(patch_text_stop_machine, &patch, NULL);
+               else
+                       __patch_text(addr, insn);
+       }
+}
diff --git a/arch/arm/kernel/patch.h b/arch/arm/kernel/patch.h
new file mode 100644 (file)
index 0000000..b4731f2
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _ARM_KERNEL_PATCH_H
+#define _ARM_KERNEL_PATCH_H
+
+void patch_text(void *addr, unsigned int insn);
+void __patch_text(void *addr, unsigned int insn);
+
+#endif
index 8a89d3b7626b2fd6e7e984f6561ca113b12d1081..186c8cb982c543a2cc1631796b34376151b33702 100644 (file)
@@ -738,6 +738,9 @@ init_hw_perf_events(void)
                case 0xC0F0:    /* Cortex-A15 */
                        cpu_pmu = armv7_a15_pmu_init();
                        break;
+               case 0xC070:    /* Cortex-A7 */
+                       cpu_pmu = armv7_a7_pmu_init();
+                       break;
                }
        /* Intel CPUs [xscale]. */
        } else if (0x69 == implementor) {
index 4d7095af2ab3a55075f080b3d4fee66b84d39f17..00755d82e2f2cbe06cda363c53ff115397d94d59 100644 (file)
@@ -609,6 +609,130 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
        },
 };
 
+/*
+ * Cortex-A7 HW events mapping
+ */
+static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV7_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]            = ARMV7_PERFCTR_INSTR_EXECUTED,
+       [PERF_COUNT_HW_CACHE_REFERENCES]        = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+       [PERF_COUNT_HW_CACHE_MISSES]            = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = ARMV7_PERFCTR_PC_WRITE,
+       [PERF_COUNT_HW_BRANCH_MISSES]           = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]              = ARMV7_PERFCTR_BUS_CYCLES,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                       [PERF_COUNT_HW_CACHE_OP_MAX]
+                                       [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_CACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_CACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(NODE)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
 /*
  * Perf Events' indices
  */
@@ -1104,6 +1228,12 @@ static int armv7_a15_map_event(struct perf_event *event)
                                &armv7_a15_perf_cache_map, 0xFF);
 }
 
+static int armv7_a7_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv7_a7_perf_map,
+                               &armv7_a7_perf_cache_map, 0xFF);
+}
+
 static struct arm_pmu armv7pmu = {
        .handle_irq             = armv7pmu_handle_irq,
        .enable                 = armv7pmu_enable_event,
@@ -1164,6 +1294,16 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
        armv7pmu.set_event_filter = armv7pmu_set_event_filter;
        return &armv7pmu;
 }
+
+static struct arm_pmu *__init armv7_a7_pmu_init(void)
+{
+       armv7pmu.id             = ARM_PERF_PMU_ID_CA7;
+       armv7pmu.name           = "ARMv7 Cortex-A7";
+       armv7pmu.map_event      = armv7_a7_map_event;
+       armv7pmu.num_events     = armv7_read_num_pmnc_events();
+       armv7pmu.set_event_filter = armv7pmu_set_event_filter;
+       return &armv7pmu;
+}
 #else
 static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
@@ -1184,4 +1324,9 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
        return NULL;
 }
+
+static struct arm_pmu *__init armv7_a7_pmu_init(void)
+{
+       return NULL;
+}
 #endif /* CONFIG_CPU_V7 */
index d3eca4524533ccd0b6f36d19cee44957b9cf938b..2b7b017a20cd6fe9e1644e61ab1f5fe03f7d1be0 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/cacheflush.h>
 #include <asm/leds.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/thread_notify.h>
 #include <asm/stacktrace.h>
 #include <asm/mach/time.h>
@@ -529,21 +528,39 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 #ifdef CONFIG_MMU
 /*
  * The vectors page is always readable from user space for the
- * atomic helpers and the signal restart code.  Let's declare a mapping
- * for it so it is visible through ptrace and /proc/<pid>/mem.
+ * atomic helpers and the signal restart code. Insert it into the
+ * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
  */
+static struct vm_area_struct gate_vma;
 
-int vectors_user_mapping(void)
+static int __init gate_vma_init(void)
 {
-       struct mm_struct *mm = current->mm;
-       return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
-                                      VM_READ | VM_EXEC |
-                                      VM_MAYREAD | VM_MAYEXEC | VM_RESERVED,
-                                      NULL);
+       gate_vma.vm_start       = 0xffff0000;
+       gate_vma.vm_end         = 0xffff0000 + PAGE_SIZE;
+       gate_vma.vm_page_prot   = PAGE_READONLY_EXEC;
+       gate_vma.vm_flags       = VM_READ | VM_EXEC |
+                                 VM_MAYREAD | VM_MAYEXEC;
+       return 0;
+}
+arch_initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+       return &gate_vma;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+       return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end);
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+       return in_gate_area(NULL, addr);
 }
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-       return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
+       return (vma == &gate_vma) ? "[vectors]" : NULL;
 }
 #endif
index ede6443c34d964670560f155aaf200ed6bf0949e..45956c9d0ef0d383dc60a41ba20be10256d029e8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/audit.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #define REG_PC 15
index 5416c7c125289b201cb5c8db3c27b9bf8eeea298..27d186abbc06f8aa3aa6310faa5b67039d447f03 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/syscore_ops.h>
 #include <linux/timer.h>
 
 #include <asm/sched_clock.h>
@@ -164,3 +165,20 @@ void __init sched_clock_postinit(void)
 
        sched_clock_poll(sched_clock_timer.data);
 }
+
+static int sched_clock_suspend(void)
+{
+       sched_clock_poll(sched_clock_timer.data);
+       return 0;
+}
+
+static struct syscore_ops sched_clock_ops = {
+       .suspend = sched_clock_suspend,
+};
+
+static int __init sched_clock_syscore_init(void)
+{
+       register_syscore_ops(&sched_clock_ops);
+       return 0;
+}
+device_initcall(sched_clock_syscore_init);
index a255c39612ca3cfa10bddb7c7728216efeeb04d5..b91411371ae19b1ae75c2184b4b26ec6c9b06193 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/sort.h>
 
 #include <asm/unified.h>
+#include <asm/cp15.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 
 #include <asm/prom.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/system_info.h>
+#include <asm/system_misc.h>
 #include <asm/traps.h>
 #include <asm/unwind.h>
 #include <asm/memblock.h>
@@ -974,7 +976,6 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
-       early_trap_init();
 
        if (mdesc->init_early)
                mdesc->init_early();
index 9e617bd4a146250d7d3f453d50a45431fa261e08..7cb532fc8aa4e3a9dc1e9d63d4cb887a08b1fad1 100644 (file)
@@ -66,12 +66,13 @@ const unsigned long syscall_restart_code[2] = {
  */
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
+       sigset_t blocked;
+
        current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+
+       mask &= _BLOCKABLE;
+       siginitset(&blocked, mask);
+       set_current_blocked(&blocked);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -280,10 +281,7 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
        err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
        if (err == 0) {
                sigdelsetmask(&set, ~_BLOCKABLE);
-               spin_lock_irq(&current->sighand->siglock);
-               current->blocked = set;
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
+               set_current_blocked(&set);
        }
 
        __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
@@ -636,13 +634,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
        /*
         * Block the signal if we were successful.
         */
-       spin_lock_irq(&tsk->sighand->siglock);
-       sigorsets(&tsk->blocked, &tsk->blocked,
-                 &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&tsk->blocked, sig);
-       recalc_sigpending();
-       spin_unlock_irq(&tsk->sighand->siglock);
+       block_sigmask(ka, sig);
 
        return 0;
 }
index 1f268bda45528ebd0e52c88ddb9bdf40f5e12e03..987dcf33415c420f70dc08852da45bd654a21ea2 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/assembler.h>
 #include <asm/glue-cache.h>
 #include <asm/glue-proc.h>
-#include <asm/system.h>
        .text
 
 /*
index 8f8cce2c46c42d8a10427b77014abb5008a2530c..2cee7d1eb958bc39b19b31f18447fe4c6119419a 100644 (file)
@@ -58,6 +58,8 @@ enum ipi_msg_type {
        IPI_CPU_STOP,
 };
 
+static DECLARE_COMPLETION(cpu_running);
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
        struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -98,20 +100,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
         */
        ret = boot_secondary(cpu, idle);
        if (ret == 0) {
-               unsigned long timeout;
-
                /*
                 * CPU was successfully started, wait for it
                 * to come online or time out.
                 */
-               timeout = jiffies + HZ;
-               while (time_before(jiffies, timeout)) {
-                       if (cpu_online(cpu))
-                               break;
-
-                       udelay(10);
-                       barrier();
-               }
+               wait_for_completion_timeout(&cpu_running,
+                                                msecs_to_jiffies(1000));
 
                if (!cpu_online(cpu)) {
                        pr_crit("CPU%u: failed to come online\n", cpu);
@@ -288,9 +282,10 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        /*
         * OK, now it's safe to let the boot CPU continue.  Wait for
         * the CPU migration code to notice that the CPU is online
-        * before we continue.
+        * before we continue - which happens after __cpu_up returns.
         */
        set_cpu_online(cpu, true);
+       complete(&cpu_running);
 
        /*
         * Setup the percpu timer for this CPU.
index 7dcb35285be7bd0d805c303f3dfc64d2ef74ebfb..02c5d2ce23bf121f17479bba2b52460419481930 100644 (file)
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
 
-static void on_each_cpu_mask(void (*func)(void *), void *info, int wait,
-       const struct cpumask *mask)
-{
-       preempt_disable();
-
-       smp_call_function_many(mask, func, info, wait);
-       if (cpumask_test_cpu(smp_processor_id(), mask))
-               func(info);
-
-       preempt_enable();
-}
-
 /**********************************************************************/
 
 /*
@@ -87,7 +75,7 @@ void flush_tlb_all(void)
 void flush_tlb_mm(struct mm_struct *mm)
 {
        if (tlb_ops_need_broadcast())
-               on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
+               on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
        else
                local_flush_tlb_mm(mm);
 }
@@ -98,7 +86,8 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
                struct tlb_args ta;
                ta.ta_vma = vma;
                ta.ta_start = uaddr;
-               on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
+               on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page,
+                                       &ta, 1);
        } else
                local_flush_tlb_page(vma, uaddr);
 }
@@ -121,7 +110,8 @@ void flush_tlb_range(struct vm_area_struct *vma,
                ta.ta_vma = vma;
                ta.ta_start = start;
                ta.ta_end = end;
-               on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
+               on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range,
+                                       &ta, 1);
        } else
                local_flush_tlb_range(vma, start, end);
 }
index 01ec453bb924de3f48cab22c3a61362384a8957a..30ae6bb4a310c12723b7bc7ca26ea91ae25bb770 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/cputype.h>
 #include <asm/mach/map.h>
 #include <asm/memory.h>
+#include <asm/system_info.h>
 #include "tcm.h"
 
 static struct gen_pool *tcm_pool;
index 9cb7aaca159fa6aa714b29367871a24beb988c07..aab899764053d639a208e241357646e9dc20407b 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <asm/system_info.h>
 #include <asm/thread_notify.h>
 
 /*
index 8c57dd3680e9eeee46f5476d10c4c295c8796568..fe31b22f18fdd8a2bc3a8553626ba0903c4d8d13 100644 (file)
@@ -25,8 +25,6 @@
 #include <linux/timer.h>
 #include <linux/irq.h>
 
-#include <linux/mc146818rtc.h>
-
 #include <asm/leds.h>
 #include <asm/thread_info.h>
 #include <asm/sched_clock.h>
@@ -149,8 +147,6 @@ void __init time_init(void)
 {
        system_timer = machine_desc->timer;
        system_timer->init();
-#ifdef CONFIG_HAVE_SCHED_CLOCK
        sched_clock_postinit();
-#endif
 }
 
index f84dfe67724fa6e81e7975abfa08ad23a2ba3788..778454750a6c323037e382ce8353443e63da36d3 100644 (file)
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/exception.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
 #include <asm/unwind.h>
 #include <asm/tls.h>
+#include <asm/system_misc.h>
 
 #include "signal.h"
 
@@ -227,6 +227,11 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
 #else
 #define S_SMP ""
 #endif
+#ifdef CONFIG_THUMB2_KERNEL
+#define S_ISA " THUMB2"
+#else
+#define S_ISA " ARM"
+#endif
 
 static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 {
@@ -234,8 +239,8 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
        static int die_counter;
        int ret;
 
-       printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
-              str, err, ++die_counter);
+       printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP
+              S_ISA "\n", str, err, ++die_counter);
 
        /* trap and error numbers are mostly meaningless on ARM */
        ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
@@ -784,18 +789,16 @@ static void __init kuser_get_tls_init(unsigned long vectors)
                memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4);
 }
 
-void __init early_trap_init(void)
+void __init early_trap_init(void *vectors_base)
 {
-#if defined(CONFIG_CPU_USE_DOMAINS)
-       unsigned long vectors = CONFIG_VECTORS_BASE;
-#else
-       unsigned long vectors = (unsigned long)vectors_page;
-#endif
+       unsigned long vectors = (unsigned long)vectors_base;
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
        extern char __kuser_helper_start[], __kuser_helper_end[];
        int kuser_sz = __kuser_helper_end - __kuser_helper_start;
 
+       vectors_page = vectors_base;
+
        /*
         * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
         * into the vector page, mapped at 0xffff0000, and ensure these
index 0df1045311e420e2e96670e62f182f44d39f5481..364c19357e608375d58eb9835223aa60c7b9e916 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/at91rm9200.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_st.h>
index d1e5750a6a047f5160022dceb4ea5ad065461488..46f7742332988d040dbaf1d49317e4dffcea174f 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
index 684c5dfd92ac5a00eaf736ed5d5949769f4bdbd4..7de81e6222f1fdae6ed8a3618e555d2d56b5d699 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
 #include <mach/at91_pmc.h>
index 0b4fa5a7f685907d03aa4efc89a758e0e26d4230..ef301be665758763a011d3c4aed827da5dbb6fc2 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
index df3bceacc86c13ce560135010deb7f1d54c5ef08..d222f8333dab8799920b0ce025ff4e334537eb5c 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
index 4320b2096789c73a4c5110af51324472f80890c4..698479f1e197cf5725139bf135eb0c89f0d5d715 100644 (file)
@@ -437,7 +437,6 @@ void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
 
        /* DMA slave channel configuration */
        atslave->dma_dev = &at_hdmac_device.dev;
-       atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
        atslave->cfg = ATC_FIFOCFG_HALFFIFO
                        | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
        atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
index 63d9372eb18efe2f9d476aa85c7d9e4f724ef4b7..d9f2774f385eb68fffc337050602592d7bcd07e9 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
index 187cb58345c09cb223f5fbafbf1635fd6653f5cd..fff48d1a0f4efad0a6ca03619cda828e7acfafe3 100644 (file)
@@ -23,18 +23,6 @@ struct at_dma_platform_data {
        dma_cap_mask_t  cap_mask;
 };
 
-/**
- * enum at_dma_slave_width - DMA slave register access width.
- * @AT_DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
- * @AT_DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
- * @AT_DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
- */
-enum at_dma_slave_width {
-       AT_DMA_SLAVE_WIDTH_8BIT = 0,
-       AT_DMA_SLAVE_WIDTH_16BIT,
-       AT_DMA_SLAVE_WIDTH_32BIT,
-};
-
 /**
  * struct at_dma_slave - Controller-specific information about a slave
  * @dma_dev: required DMA master device
@@ -48,9 +36,6 @@ enum at_dma_slave_width {
  */
 struct at_dma_slave {
        struct device           *dma_dev;
-       dma_addr_t              tx_reg;
-       dma_addr_t              rx_reg;
-       enum at_dma_slave_width reg_width;
        u32                     cfg;
        u32                     ctrla;
 };
diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h
deleted file mode 100644 (file)
index 4003001..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/io.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include <mach/hardware.h>
-
-#define IO_SPACE_LIMIT         0xFFFFFFFF
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index ec164a4124c9b27aa0c3b72325dc91ec13ddc673..ef79a9aafc08495c11cab9a5bd31c67ec8de24a2 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef __ARCH_SYSTEM_REV_H__
 #define __ARCH_SYSTEM_REV_H__
 
+#include <asm/system_info.h>
+
 /*
  * board revision encoding
  * mach specific
index 0234fd9d20d6f13dc81f6e98984a22e954b03aeb..4218647c1fcd3279a39bb83b8b38eb7cdb5aa743 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/io.h>
 #include <linux/atmel_serial.h>
+#include <mach/hardware.h>
 
 #if defined(CONFIG_AT91_EARLY_DBGU0)
 #define UART_OFFSET AT91_BASE_DBGU0
diff --git a/arch/arm/mach-bcmring/include/mach/io.h b/arch/arm/mach-bcmring/include/mach/io.h
deleted file mode 100644 (file)
index dae5e9b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#include <mach/hardware.h>
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 8736c1acc166c7bf826e9c112ecb67de650a175a..3c5b5bbf24e51e991bc142ae09f3016e5b7e294a 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/hardware/clps7111.h>
+#include <asm/system_misc.h>
 
 /*
  * This maps the generic CLPS711x registers
diff --git a/arch/arm/mach-clps711x/include/mach/io.h b/arch/arm/mach-clps711x/include/mach/io.h
deleted file mode 100644 (file)
index 2e0b3ce..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  arch/arm/mach-clps711x/include/mach/io.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-/*
- * We don't support ins[lb]/outs[lb].  Make them fault.
- */
-#define __raw_readsb(p,d,l)    do { *(int *)0 = 0; } while (0)
-#define __raw_readsl(p,d,l)    do { *(int *)0 = 0; } while (0)
-#define __raw_writesb(p,d,l)   do { *(int *)0 = 0; } while (0)
-#define __raw_writesl(p,d,l)   do { *(int *)0 = 0; } while (0)
-
-#endif
index 7164310dea7cdbbfc950242cd9c8f7da2006bc66..35ed731b9f160e8476278964da62d040e3d83b60 100644 (file)
@@ -17,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <mach/io.h>
 #include <mach/hardware.h>
 #include <asm/hardware/clps7111.h>
 
index 15121446efc870ad2e083e14ba2862a948421492..dd9a6cdbeb020ff169fccfb33965923e5e2680d8 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include <asm/hardware/clps7111.h>
index 941a308e12533e859b0eddeb17998931921591f1..031805b1428dc1d6196d7201637ad05e865c9553 100644 (file)
@@ -72,13 +72,13 @@ void __init cns3xxx_map_io(void)
 /* used by entry-macro.S */
 void __init cns3xxx_init_irq(void)
 {
-       gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
-                __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
+       gic_init(0, 29, IOMEM(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
+                IOMEM(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
 }
 
 void cns3xxx_power_off(void)
 {
-       u32 __iomem *pm_base = __io(CNS3XXX_PM_BASE_VIRT);
+       u32 __iomem *pm_base = IOMEM(CNS3XXX_PM_BASE_VIRT);
        u32 clkctrl;
 
        printk(KERN_INFO "powering system down...\n");
@@ -237,7 +237,7 @@ static void __init __cns3xxx_timer_init(unsigned int timer_irq)
 
 static void __init cns3xxx_timer_init(void)
 {
-       cns3xxx_tmr1 = __io(CNS3XXX_TIMER1_2_3_BASE_VIRT);
+       cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT);
 
        __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
 }
index 79d1fb02c23fdba10279d1e2e4af1d22220e5494..1e40c99b015f7d44c5c0ab19a2f4d9fbff7baede 100644 (file)
@@ -98,7 +98,7 @@ static struct platform_device cns3xxx_sdhci_pdev = {
 
 void __init cns3xxx_sdhci_init(void)
 {
-       u32 __iomem *gpioa = __io(CNS3XXX_MISC_BASE_VIRT + 0x0014);
+       u32 __iomem *gpioa = IOMEM(CNS3XXX_MISC_BASE_VIRT + 0x0014);
        u32 gpioa_pins = __raw_readl(gpioa);
 
        /* MMC/SD pins share with GPIOA */
diff --git a/arch/arm/mach-cns3xxx/include/mach/io.h b/arch/arm/mach-cns3xxx/include/mach/io.h
deleted file mode 100644 (file)
index 33b6fc1..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- * Copyright 2003 ARM Limited
- *
- * This file 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.
- */
-#ifndef __MACH_IO_H
-#define __MACH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                        __typesafe_io(a)
-#define __mem_pci(a)           (a)
-
-#endif
index d5088900af6c89a41eae892fb80be4d88fc8a73d..a70de24d1cbc5ea112e43c54db3b2183d5f53ba1 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
index c1661d2feca9ff7783e7c5d52e0ee3911cc25df9..768b3c0602140e789286b7182bb07e2b31336282 100644 (file)
@@ -8,7 +8,6 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#include <mach/io.h>
 #include <mach/irqs.h>
 
                .macro  get_irqnr_preamble, base, tmp
index 0209b1fc22a1dad995e4fdefc2221b7d6ca32561..2184691ebc2f78ddfcb5989e2d880ac77a5d3749 100644 (file)
 #define __IO_ADDRESS(x)                        ((x) + IO_OFFSET)
 #define IO_ADDRESS(pa)                 IOMEM(__IO_ADDRESS(pa))
 
-#ifdef __ASSEMBLER__
-#define IOMEM(x)                       x
-#else
-#define IOMEM(x)                       ((void __force __iomem *)(x))
-#endif
-
 #endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h
deleted file mode 100644 (file)
index b2267d1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * DaVinci IO address definitions
- *
- * Copied from include/asm/arm/arch-omap/io.h
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                        __typesafe_io(a)
-#define __mem_pci(a)           (a)
-#define __mem_isa(a)           (a)
-
-#endif /* __ASM_ARCH_IO_H */
index 9dc7cf9664feefcf6816c4246fa69921140bf612..da2fb2c2155a2ac84d242ad76c4de2842aa33d31 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <mach/serial.h>
 
+#define IOMEM(x)       ((void __force __iomem *)(x))
+
 u32 *uart;
 
 /* PORT_16C550A, in polled non-fifo mode */
index e1969ce904dc5b4de9ff8f0d44442175c7c2497f..75da315b658724fabe134cb40fef3015b2df9697 100644 (file)
 #include <linux/err.h>
 #include <linux/platform_device.h>
 
-#include <mach/hardware.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+
 #include <mach/cputype.h>
+#include <mach/hardware.h>
 #include <mach/time.h>
+
 #include "clock.h"
 
 static struct clock_event_device clockevent_davinci;
@@ -272,19 +275,9 @@ static cycle_t read_cycles(struct clocksource *cs)
        return (cycles_t)timer32_read(t);
 }
 
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t read_dummy(struct clocksource *cs)
-{
-       return 0;
-}
-
-
 static struct clocksource clocksource_davinci = {
        .rating         = 300,
-       .read           = read_dummy,
+       .read           = read_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
@@ -292,12 +285,9 @@ static struct clocksource clocksource_davinci = {
 /*
  * Overwrite weak default sched_clock with something more precise
  */
-unsigned long long notrace sched_clock(void)
+static u32 notrace davinci_read_sched_clock(void)
 {
-       const cycle_t cyc = clocksource_davinci.read(&clocksource_davinci);
-
-       return clocksource_cyc2ns(cyc, clocksource_davinci.mult,
-                               clocksource_davinci.shift);
+       return timer32_read(&timers[TID_CLOCKSOURCE]);
 }
 
 /*
@@ -397,12 +387,14 @@ static void __init davinci_timer_init(void)
        davinci_clock_tick_rate = clk_get_rate(timer_clk);
 
        /* setup clocksource */
-       clocksource_davinci.read = read_cycles;
        clocksource_davinci.name = id_to_name[clocksource_id];
        if (clocksource_register_hz(&clocksource_davinci,
                                    davinci_clock_tick_rate))
                printk(err, clocksource_davinci.name);
 
+       setup_sched_clock(davinci_read_sched_clock, 32,
+                         davinci_clock_tick_rate);
+
        /* setup clockevent */
        clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
        clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
index 98b8c83b09ab447415abe15927f7b26c0fc47e5e..2a06c0163418bcb641ee8fc2f00983afc519ed06 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
+#include <mach/dove.h>
 #include <plat/addr-map.h>
 #include "common.h"
 
index eb4936ff90ad9c42b283fc6c354eae1f01c6c4c7..29c8b85355a5243db77f468d32d80d6695993468 100644 (file)
@@ -15,6 +15,5 @@
 
 #define __io(a)        ((void __iomem *)(((a) - DOVE_PCIE0_IO_BUS_BASE) + \
                                                 DOVE_PCIE0_IO_VIRT_BASE))
-#define __mem_pci(a)   (a)
 
 #endif
index e400d75d11aee5eb0e575bf1268e99a79259387f..6f8068692edf151ea4cbe01afc266fd334df5df8 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -116,6 +116,20 @@ static void __init ebsa110_map_io(void)
        iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc));
 }
 
+static void __iomem *ebsa110_ioremap_caller(unsigned long cookie, size_t size,
+                                           unsigned int flags, void *caller)
+{
+       return (void __iomem *)cookie;
+}
+
+static void ebsa110_iounmap(volatile void __iomem *io_addr)
+{}
+
+static void __init ebsa110_init_early(void)
+{
+       arch_ioremap_caller = ebsa110_ioremap_caller;
+       arch_iounmap = ebsa110_iounmap;
+}
 
 #define PIT_CTRL               (PIT_BASE + 0x0d)
 #define PIT_T2                 (PIT_BASE + 0x09)
@@ -312,6 +326,7 @@ MACHINE_START(EBSA110, "EBSA110")
        .reserve_lp2    = 1,
        .restart_mode   = 's',
        .map_io         = ebsa110_map_io,
+       .init_early     = ebsa110_init_early,
        .init_irq       = ebsa110_init_irq,
        .timer          = &ebsa110_timer,
        .restart        = ebsa110_restart,
index 44679db672fbf54b1a55adc0304593e458545ef5..11bb0799424b537873adb81761f94bdc97c36b91 100644 (file)
@@ -62,15 +62,6 @@ void __writel(u32 val, void __iomem *addr);
 #define writew(v,b)            __writew(v,b)
 #define writel(v,b)            __writel(v,b)
 
-static inline void __iomem *__arch_ioremap(unsigned long cookie, size_t size,
-                                          unsigned int flags)
-{
-       return (void __iomem *)cookie;
-}
-
-#define __arch_ioremap         __arch_ioremap
-#define __arch_iounmap(cookie) do { } while (0)
-
 extern void insb(unsigned int port, void *buf, int sz);
 extern void insw(unsigned int port, void *buf, int sz);
 extern void insl(unsigned int port, void *buf, int sz);
index d43121a30aa783065e52dd7f87a5f09cbcc277a9..99e14e3625003568f46f42bf1da6720163b1f588 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include "core.h"
diff --git a/arch/arm/mach-ep93xx/include/mach/io.h b/arch/arm/mach-ep93xx/include/mach/io.h
deleted file mode 100644 (file)
index 594b77f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/io.h
- */
-
-#ifndef __ASM_MACH_IO_H
-#define __ASM_MACH_IO_H
-
-#define IO_SPACE_LIMIT         0xffffffff
-
-#define __io(p)                        __typesafe_io(p)
-#define __mem_pci(p)           (p)
-
-/*
- * A typesafe __io() variation for variable initialisers
- */
-#ifdef __ASSEMBLER__
-#define IOMEM(p)               p
-#else
-#define IOMEM(p)               ((void __iomem __force *)(p))
-#endif
-
-#endif /* __ASM_MACH_IO_H */
index dd1ad55524c97e0d28f270e93e10f00dab7327b8..9c17a0a43858d84df39cab4ddc8d417ba1b644a5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 
 #include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos/include/mach/io.h b/arch/arm/mach-exynos/include/mach/io.h
deleted file mode 100644 (file)
index d5478d2..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/io.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/io.h
- *
- * Default IO routines for EXYNOS4
- *
- * 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.
-*/
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H __FILE__
-
-/* No current ISA/PCI bus support. */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif /* __ASM_ARM_ARCH_IO_H */
index 82ea6fccfb3450e54487b24ead9e12c2af589e9b..b3982c867c9c5e9243c505d41b9914b69c130b30 100644 (file)
@@ -111,7 +111,7 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
        .max_width              = 8,
        .host_caps              = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
                                MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-                               MMC_CAP_DISABLE | MMC_CAP_ERASE),
+                               MMC_CAP_ERASE),
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
        .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
@@ -150,8 +150,7 @@ static struct platform_device emmc_fixed_voltage = {
 static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
        .max_width              = 4,
        .host_caps              = MMC_CAP_4_BIT_DATA |
-                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-                               MMC_CAP_DISABLE,
+                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
        .ext_cd_gpio            = EXYNOS4_GPX3(3),      /* XEINT_27 */
        .ext_cd_gpio_invert     = 1,
        .cd_type                = S3C_SDHCI_CD_GPIO,
index 28658da9f4230e8d17c000e4fec5ca696fb39373..6bb9dbdd73fdde842bcad0cb75f4713316c4a760 100644 (file)
@@ -745,8 +745,7 @@ static struct platform_device universal_gpio_keys = {
 static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
        .max_width              = 8,
        .host_caps              = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
-                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-                               MMC_CAP_DISABLE),
+                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
        .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
@@ -784,8 +783,7 @@ static struct platform_device mmc0_fixed_voltage = {
 static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
        .max_width              = 4,
        .host_caps              = MMC_CAP_4_BIT_DATA |
-                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-                               MMC_CAP_DISABLE,
+                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
        .ext_cd_gpio            = EXYNOS4_GPX3(4),      /* XEINT_28 */
        .ext_cd_gpio_invert     = 1,
        .cd_type                = S3C_SDHCI_CD_GPIO,
@@ -796,8 +794,7 @@ static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
 static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
        .max_width              = 4,
        .host_caps              = MMC_CAP_4_BIT_DATA |
-                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-                               MMC_CAP_DISABLE,
+                               MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
        .cd_type                = S3C_SDHCI_CD_EXTERNAL,
 };
 
index 41978ee4f9d0424639422adaa82789f0064c0776..3e6aaa6361da5095761b0adcd6a5d04549481bc4 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 #include <asm/hardware/dec21285.h>
 
 #include <asm/mach/irq.h>
index 121ad1d4fa39f9a0d4f70c6cbd23021f4e62617f..3b54196447c71341b31112ac378abae4ebd8f53f 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/hardware/dec21285.h>
 #include <asm/mach/time.h>
+#include <asm/system_info.h>
 
 #include "common.h"
 
index 3194d3f73503fe32efaf86cdecd46442e6afbcf9..e17e11de4f5e4a2c79682be42f4f1478353bcf36 100644 (file)
@@ -21,7 +21,6 @@
 #include <video/vga.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/hardware/dec21285.h>
 
index 4e10090cd87fb107cb82ab629826b5e420c7aa53..5bd266754b95f4eb571fd91eb14087418430039a 100644 (file)
@@ -24,7 +24,6 @@
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
 #define LED_STATE_CLAIMED      2
index 15a70396c27d41f123910fdd9cd7844d2d2cf033..aba531eebbc6723cfe5ea69c31634caac46a160b 100644 (file)
  * Translation of various region addresses to virtual addresses
  */
 #define __io(a)                        ((void __iomem *)(PCIO_BASE + (a)))
-#if 1
-#define __mem_pci(a)           (a)
-#else
-
-static inline void __iomem *___mem_pci(void __iomem *p)
-{
-       unsigned long a = (unsigned long)p;
-       BUG_ON(a <= 0xc0000000 || a >= 0xe0000000);
-       return p;
-}
-
-#define __mem_pci(a)           ___mem_pci(a)
-#endif
 
 #endif
index 80a1c5cc9071bb345fb19c5c19d6881695f808a2..cac9f67e7da7e195f4bdb98aaa5d0f1808315c22 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/arch.h>
 
index e57102e871fcd4926e12a94b262c5bf5e36f9e2e..5a2bd89cbdca56837e6781051c515d99a717b907 100644 (file)
@@ -24,7 +24,6 @@
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
 #define LED_STATE_CLAIMED      2
diff --git a/arch/arm/mach-gemini/include/mach/io.h b/arch/arm/mach-gemini/include/mach/io.h
deleted file mode 100644 (file)
index c548056..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __MACH_IO_H
-#define __MACH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif /* __MACH_IO_H */
diff --git a/arch/arm/mach-h720x/include/mach/io.h b/arch/arm/mach-h720x/include/mach/io.h
deleted file mode 100644 (file)
index 2c8659c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-h720x/include/mach/io.h
- *
- * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
- *
- * Changelog:
- *
- *  09-19-2001 JJKIM
- *             Created from arch/arm/mach-l7200/include/mach/io.h
- *
- *  03-27-2003  Robert Schwebel <r.schwebel@pengutronix.de>:
- *             re-unified header files for h720x
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 808b055289b2b0443cf5f197e47f3eac11aa6679..410a112bb52e29036d22c1de07ffed1965011389 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/irqs.h>
 
 #include "core.h"
 #include "sysregs.h"
diff --git a/arch/arm/mach-highbank/include/mach/io.h b/arch/arm/mach-highbank/include/mach/io.h
deleted file mode 100644 (file)
index 70cfa3b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_IO_H
-#define __MACH_IO_H
-
-#define __io(a)                ({ (void)(a); __typesafe_io(0); })
-#define __mem_pci(a)   (a)
-
-#endif
diff --git a/arch/arm/mach-highbank/include/mach/irqs.h b/arch/arm/mach-highbank/include/mach/irqs.h
deleted file mode 100644 (file)
index 9746aab..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MACH_IRQS_H
-#define __MACH_IRQS_H
-
-#define NR_IRQS                        192
-
-#endif
index 52359f80c42d1b2e2bbe06fc93d1e72d389649e3..7561eca131b0ba989c42afb1a5ec94fbce98f688 100644 (file)
@@ -1,6 +1,3 @@
-config IMX_HAVE_DMA_V1
-       bool
-
 config HAVE_IMX_GPC
        bool
 
@@ -38,7 +35,6 @@ config SOC_IMX1
        bool
        select ARCH_MX1
        select CPU_ARM920T
-       select IMX_HAVE_DMA_V1
        select IMX_HAVE_IOMUX_V1
        select MXC_AVIC
 
@@ -46,7 +42,6 @@ config SOC_IMX21
        bool
        select MACH_MX21
        select CPU_ARM926T
-       select IMX_HAVE_DMA_V1
        select IMX_HAVE_IOMUX_V1
        select MXC_AVIC
 
@@ -61,7 +56,6 @@ config SOC_IMX27
        bool
        select MACH_MX27
        select CPU_ARM926T
-       select IMX_HAVE_DMA_V1
        select IMX_HAVE_IOMUX_V1
        select MXC_AVIC
 
index 35fc450fa263c2eb1e3d08d4bccd2c389e9b2105..ab939c5046c37080692a37592944ccfa7a2c4100 100644 (file)
@@ -1,5 +1,3 @@
-obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
-
 obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
deleted file mode 100644 (file)
index 42afc29..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-/*
- *  linux/arch/arm/plat-mxc/dma-v1.c
- *
- *  i.MX DMA registration and IRQ dispatching
- *
- * Copyright 2006 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- * Copyright 2008 Juergen Beisert, <kernel@pengutronix.de>
- * Copyright 2008 Sascha Hauer, <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/scatterlist.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/dma-v1.h>
-
-#define DMA_DCR     0x00               /* Control Register */
-#define DMA_DISR    0x04               /* Interrupt status Register */
-#define DMA_DIMR    0x08               /* Interrupt mask Register */
-#define DMA_DBTOSR  0x0c               /* Burst timeout status Register */
-#define DMA_DRTOSR  0x10               /* Request timeout Register */
-#define DMA_DSESR   0x14               /* Transfer Error Status Register */
-#define DMA_DBOSR   0x18               /* Buffer overflow status Register */
-#define DMA_DBTOCR  0x1c               /* Burst timeout control Register */
-#define DMA_WSRA    0x40               /* W-Size Register A */
-#define DMA_XSRA    0x44               /* X-Size Register A */
-#define DMA_YSRA    0x48               /* Y-Size Register A */
-#define DMA_WSRB    0x4c               /* W-Size Register B */
-#define DMA_XSRB    0x50               /* X-Size Register B */
-#define DMA_YSRB    0x54               /* Y-Size Register B */
-#define DMA_SAR(x)  (0x80 + ((x) << 6))        /* Source Address Registers */
-#define DMA_DAR(x)  (0x84 + ((x) << 6))        /* Destination Address Registers */
-#define DMA_CNTR(x) (0x88 + ((x) << 6))        /* Count Registers */
-#define DMA_CCR(x)  (0x8c + ((x) << 6))        /* Control Registers */
-#define DMA_RSSR(x) (0x90 + ((x) << 6))        /* Request source select Registers */
-#define DMA_BLR(x)  (0x94 + ((x) << 6))        /* Burst length Registers */
-#define DMA_RTOR(x) (0x98 + ((x) << 6))        /* Request timeout Registers */
-#define DMA_BUCR(x) (0x98 + ((x) << 6))        /* Bus Utilization Registers */
-#define DMA_CCNR(x) (0x9C + ((x) << 6))        /* Channel counter Registers */
-
-#define DCR_DRST           (1<<1)
-#define DCR_DEN            (1<<0)
-#define DBTOCR_EN          (1<<15)
-#define DBTOCR_CNT(x)      ((x) & 0x7fff)
-#define CNTR_CNT(x)        ((x) & 0xffffff)
-#define CCR_ACRPT          (1<<14)
-#define CCR_DMOD_LINEAR    (0x0 << 12)
-#define CCR_DMOD_2D        (0x1 << 12)
-#define CCR_DMOD_FIFO      (0x2 << 12)
-#define CCR_DMOD_EOBFIFO   (0x3 << 12)
-#define CCR_SMOD_LINEAR    (0x0 << 10)
-#define CCR_SMOD_2D        (0x1 << 10)
-#define CCR_SMOD_FIFO      (0x2 << 10)
-#define CCR_SMOD_EOBFIFO   (0x3 << 10)
-#define CCR_MDIR_DEC       (1<<9)
-#define CCR_MSEL_B         (1<<8)
-#define CCR_DSIZ_32        (0x0 << 6)
-#define CCR_DSIZ_8         (0x1 << 6)
-#define CCR_DSIZ_16        (0x2 << 6)
-#define CCR_SSIZ_32        (0x0 << 4)
-#define CCR_SSIZ_8         (0x1 << 4)
-#define CCR_SSIZ_16        (0x2 << 4)
-#define CCR_REN            (1<<3)
-#define CCR_RPT            (1<<2)
-#define CCR_FRC            (1<<1)
-#define CCR_CEN            (1<<0)
-#define RTOR_EN            (1<<15)
-#define RTOR_CLK           (1<<14)
-#define RTOR_PSC           (1<<13)
-
-/*
- * struct imx_dma_channel - i.MX specific DMA extension
- * @name: name specified by DMA client
- * @irq_handler: client callback for end of transfer
- * @err_handler: client callback for error condition
- * @data: clients context data for callbacks
- * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE
- * @sg: pointer to the actual read/written chunk for scatter-gather emulation
- * @resbytes: total residual number of bytes to transfer
- *            (it can be lower or same as sum of SG mapped chunk sizes)
- * @sgcount: number of chunks to be read/written
- *
- * Structure is used for IMX DMA processing. It would be probably good
- * @struct dma_struct in the future for external interfacing and use
- * @struct imx_dma_channel only as extension to it.
- */
-
-struct imx_dma_channel {
-       const char *name;
-       void (*irq_handler) (int, void *);
-       void (*err_handler) (int, void *, int errcode);
-       void (*prog_handler) (int, void *, struct scatterlist *);
-       void *data;
-       unsigned int dma_mode;
-       struct scatterlist *sg;
-       unsigned int resbytes;
-       int dma_num;
-
-       int in_use;
-
-       u32 ccr_from_device;
-       u32 ccr_to_device;
-
-       struct timer_list watchdog;
-
-       int hw_chaining;
-};
-
-static void __iomem *imx_dmav1_baseaddr;
-
-static void imx_dmav1_writel(unsigned val, unsigned offset)
-{
-       __raw_writel(val, imx_dmav1_baseaddr + offset);
-}
-
-static unsigned imx_dmav1_readl(unsigned offset)
-{
-       return __raw_readl(imx_dmav1_baseaddr + offset);
-}
-
-static struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
-
-static struct clk *dma_clk;
-
-static int imx_dma_hw_chain(struct imx_dma_channel *imxdma)
-{
-       if (cpu_is_mx27())
-               return imxdma->hw_chaining;
-       else
-               return 0;
-}
-
-/*
- * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
- */
-static inline int imx_dma_sg_next(int channel, struct scatterlist *sg)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       unsigned long now;
-
-       if (!imxdma->name) {
-               printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-                      __func__, channel);
-               return 0;
-       }
-
-       now = min(imxdma->resbytes, sg->length);
-       if (imxdma->resbytes != IMX_DMA_LENGTH_LOOP)
-               imxdma->resbytes -= now;
-
-       if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
-               imx_dmav1_writel(sg->dma_address, DMA_DAR(channel));
-       else
-               imx_dmav1_writel(sg->dma_address, DMA_SAR(channel));
-
-       imx_dmav1_writel(now, DMA_CNTR(channel));
-
-       pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, "
-               "size 0x%08x\n", channel,
-                imx_dmav1_readl(DMA_DAR(channel)),
-                imx_dmav1_readl(DMA_SAR(channel)),
-                imx_dmav1_readl(DMA_CNTR(channel)));
-
-       return now;
-}
-
-/**
- * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from
- * device transfer
- *
- * @channel: i.MX DMA channel number
- * @dma_address: the DMA/physical memory address of the linear data block
- *             to transfer
- * @dma_length: length of the data block in bytes
- * @dev_addr: physical device port address
- * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
- *           or %DMA_MODE_WRITE from memory to the device
- *
- * Return value: if incorrect parameters are provided -%EINVAL.
- *             Zero indicates success.
- */
-int
-imx_dma_setup_single(int channel, dma_addr_t dma_address,
-                    unsigned int dma_length, unsigned int dev_addr,
-                    unsigned int dmamode)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-
-       imxdma->sg = NULL;
-       imxdma->dma_mode = dmamode;
-
-       if (!dma_address) {
-               printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
-                      channel);
-               return -EINVAL;
-       }
-
-       if (!dma_length) {
-               printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
-                      channel);
-               return -EINVAL;
-       }
-
-       if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
-               pr_debug("imxdma%d: %s dma_addressg=0x%08x dma_length=%d "
-                       "dev_addr=0x%08x for read\n",
-                       channel, __func__, (unsigned int)dma_address,
-                       dma_length, dev_addr);
-
-               imx_dmav1_writel(dev_addr, DMA_SAR(channel));
-               imx_dmav1_writel(dma_address, DMA_DAR(channel));
-               imx_dmav1_writel(imxdma->ccr_from_device, DMA_CCR(channel));
-       } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
-               pr_debug("imxdma%d: %s dma_addressg=0x%08x dma_length=%d "
-                       "dev_addr=0x%08x for write\n",
-                       channel, __func__, (unsigned int)dma_address,
-                       dma_length, dev_addr);
-
-               imx_dmav1_writel(dma_address, DMA_SAR(channel));
-               imx_dmav1_writel(dev_addr, DMA_DAR(channel));
-               imx_dmav1_writel(imxdma->ccr_to_device,
-                               DMA_CCR(channel));
-       } else {
-               printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
-                      channel);
-               return -EINVAL;
-       }
-
-       imx_dmav1_writel(dma_length, DMA_CNTR(channel));
-
-       return 0;
-}
-EXPORT_SYMBOL(imx_dma_setup_single);
-
-/**
- * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
- * @channel: i.MX DMA channel number
- * @sg: pointer to the scatter-gather list/vector
- * @sgcount: scatter-gather list hungs count
- * @dma_length: total length of the transfer request in bytes
- * @dev_addr: physical device port address
- * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
- *           or %DMA_MODE_WRITE from memory to the device
- *
- * The function sets up DMA channel state and registers to be ready for
- * transfer specified by provided parameters. The scatter-gather emulation
- * is set up according to the parameters.
- *
- * The full preparation of the transfer requires setup of more register
- * by the caller before imx_dma_enable() can be called.
- *
- * %BLR(channel) holds transfer burst length in bytes, 0 means 64 bytes
- *
- * %RSSR(channel) has to be set to the DMA request line source %DMA_REQ_xxx
- *
- * %CCR(channel) has to specify transfer parameters, the next settings is
- * typical for linear or simple scatter-gather transfers if %DMA_MODE_READ is
- * specified
- *
- * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
- *
- * The typical setup for %DMA_MODE_WRITE is specified by next options
- * combination
- *
- * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
- *
- * Be careful here and do not mistakenly mix source and target device
- * port sizes constants, they are really different:
- * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
- * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
- *
- * Return value: if incorrect parameters are provided -%EINVAL.
- * Zero indicates success.
- */
-int
-imx_dma_setup_sg(int channel,
-                struct scatterlist *sg, unsigned int sgcount,
-                unsigned int dma_length, unsigned int dev_addr,
-                unsigned int dmamode)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-
-       if (imxdma->in_use)
-               return -EBUSY;
-
-       imxdma->sg = sg;
-       imxdma->dma_mode = dmamode;
-       imxdma->resbytes = dma_length;
-
-       if (!sg || !sgcount) {
-               printk(KERN_ERR "imxdma%d: imx_dma_setup_sg empty sg list\n",
-                      channel);
-               return -EINVAL;
-       }
-
-       if (!sg->length) {
-               printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
-                      channel);
-               return -EINVAL;
-       }
-
-       if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
-               pr_debug("imxdma%d: %s sg=%p sgcount=%d total length=%d "
-                       "dev_addr=0x%08x for read\n",
-                       channel, __func__, sg, sgcount, dma_length, dev_addr);
-
-               imx_dmav1_writel(dev_addr, DMA_SAR(channel));
-               imx_dmav1_writel(imxdma->ccr_from_device, DMA_CCR(channel));
-       } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
-               pr_debug("imxdma%d: %s sg=%p sgcount=%d total length=%d "
-                       "dev_addr=0x%08x for write\n",
-                       channel, __func__, sg, sgcount, dma_length, dev_addr);
-
-               imx_dmav1_writel(dev_addr, DMA_DAR(channel));
-               imx_dmav1_writel(imxdma->ccr_to_device, DMA_CCR(channel));
-       } else {
-               printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
-                      channel);
-               return -EINVAL;
-       }
-
-       imx_dma_sg_next(channel, sg);
-
-       return 0;
-}
-EXPORT_SYMBOL(imx_dma_setup_sg);
-
-int
-imx_dma_config_channel(int channel, unsigned int config_port,
-       unsigned int config_mem, unsigned int dmareq, int hw_chaining)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       u32 dreq = 0;
-
-       imxdma->hw_chaining = 0;
-
-       if (hw_chaining) {
-               imxdma->hw_chaining = 1;
-               if (!imx_dma_hw_chain(imxdma))
-                       return -EINVAL;
-       }
-
-       if (dmareq)
-               dreq = CCR_REN;
-
-       imxdma->ccr_from_device = config_port | (config_mem << 2) | dreq;
-       imxdma->ccr_to_device = config_mem | (config_port << 2) | dreq;
-
-       imx_dmav1_writel(dmareq, DMA_RSSR(channel));
-
-       return 0;
-}
-EXPORT_SYMBOL(imx_dma_config_channel);
-
-void imx_dma_config_burstlen(int channel, unsigned int burstlen)
-{
-       imx_dmav1_writel(burstlen, DMA_BLR(channel));
-}
-EXPORT_SYMBOL(imx_dma_config_burstlen);
-
-/**
- * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification
- * handlers
- * @channel: i.MX DMA channel number
- * @irq_handler: the pointer to the function called if the transfer
- *             ends successfully
- * @err_handler: the pointer to the function called if the premature
- *             end caused by error occurs
- * @data: user specified value to be passed to the handlers
- */
-int
-imx_dma_setup_handlers(int channel,
-                      void (*irq_handler) (int, void *),
-                      void (*err_handler) (int, void *, int),
-                      void *data)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       unsigned long flags;
-
-       if (!imxdma->name) {
-               printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-                      __func__, channel);
-               return -ENODEV;
-       }
-
-       local_irq_save(flags);
-       imx_dmav1_writel(1 << channel, DMA_DISR);
-       imxdma->irq_handler = irq_handler;
-       imxdma->err_handler = err_handler;
-       imxdma->data = data;
-       local_irq_restore(flags);
-       return 0;
-}
-EXPORT_SYMBOL(imx_dma_setup_handlers);
-
-/**
- * imx_dma_setup_progression_handler - setup i.MX DMA channel progression
- * handlers
- * @channel: i.MX DMA channel number
- * @prog_handler: the pointer to the function called if the transfer progresses
- */
-int
-imx_dma_setup_progression_handler(int channel,
-                       void (*prog_handler) (int, void*, struct scatterlist*))
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       unsigned long flags;
-
-       if (!imxdma->name) {
-               printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-                      __func__, channel);
-               return -ENODEV;
-       }
-
-       local_irq_save(flags);
-       imxdma->prog_handler = prog_handler;
-       local_irq_restore(flags);
-       return 0;
-}
-EXPORT_SYMBOL(imx_dma_setup_progression_handler);
-
-/**
- * imx_dma_enable - function to start i.MX DMA channel operation
- * @channel: i.MX DMA channel number
- *
- * The channel has to be allocated by driver through imx_dma_request()
- * or imx_dma_request_by_prio() function.
- * The transfer parameters has to be set to the channel registers through
- * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
- * and registers %BLR(channel), %RSSR(channel) and %CCR(channel) has to
- * be set prior this function call by the channel user.
- */
-void imx_dma_enable(int channel)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       unsigned long flags;
-
-       pr_debug("imxdma%d: imx_dma_enable\n", channel);
-
-       if (!imxdma->name) {
-               printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
-                      __func__, channel);
-               return;
-       }
-
-       if (imxdma->in_use)
-               return;
-
-       local_irq_save(flags);
-
-       imx_dmav1_writel(1 << channel, DMA_DISR);
-       imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) & ~(1 << channel), DMA_DIMR);
-       imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) | CCR_CEN |
-               CCR_ACRPT, DMA_CCR(channel));
-
-       if ((cpu_is_mx21() || cpu_is_mx27()) &&
-                       imxdma->sg && imx_dma_hw_chain(imxdma)) {
-               imxdma->sg = sg_next(imxdma->sg);
-               if (imxdma->sg) {
-                       u32 tmp;
-                       imx_dma_sg_next(channel, imxdma->sg);
-                       tmp = imx_dmav1_readl(DMA_CCR(channel));
-                       imx_dmav1_writel(tmp | CCR_RPT | CCR_ACRPT,
-                               DMA_CCR(channel));
-               }
-       }
-       imxdma->in_use = 1;
-
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(imx_dma_enable);
-
-/**
- * imx_dma_disable - stop, finish i.MX DMA channel operatin
- * @channel: i.MX DMA channel number
- */
-void imx_dma_disable(int channel)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       unsigned long flags;
-
-       pr_debug("imxdma%d: imx_dma_disable\n", channel);
-
-       if (imx_dma_hw_chain(imxdma))
-               del_timer(&imxdma->watchdog);
-
-       local_irq_save(flags);
-       imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) | (1 << channel), DMA_DIMR);
-       imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) & ~CCR_CEN,
-                       DMA_CCR(channel));
-       imx_dmav1_writel(1 << channel, DMA_DISR);
-       imxdma->in_use = 0;
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(imx_dma_disable);
-
-static void imx_dma_watchdog(unsigned long chno)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[chno];
-
-       imx_dmav1_writel(0, DMA_CCR(chno));
-       imxdma->in_use = 0;
-       imxdma->sg = NULL;
-
-       if (imxdma->err_handler)
-               imxdma->err_handler(chno, imxdma->data, IMX_DMA_ERR_TIMEOUT);
-}
-
-static irqreturn_t dma_err_handler(int irq, void *dev_id)
-{
-       int i, disr;
-       struct imx_dma_channel *imxdma;
-       unsigned int err_mask;
-       int errcode;
-
-       disr = imx_dmav1_readl(DMA_DISR);
-
-       err_mask = imx_dmav1_readl(DMA_DBTOSR) |
-                  imx_dmav1_readl(DMA_DRTOSR) |
-                  imx_dmav1_readl(DMA_DSESR)  |
-                  imx_dmav1_readl(DMA_DBOSR);
-
-       if (!err_mask)
-               return IRQ_HANDLED;
-
-       imx_dmav1_writel(disr & err_mask, DMA_DISR);
-
-       for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-               if (!(err_mask & (1 << i)))
-                       continue;
-               imxdma = &imx_dma_channels[i];
-               errcode = 0;
-
-               if (imx_dmav1_readl(DMA_DBTOSR) & (1 << i)) {
-                       imx_dmav1_writel(1 << i, DMA_DBTOSR);
-                       errcode |= IMX_DMA_ERR_BURST;
-               }
-               if (imx_dmav1_readl(DMA_DRTOSR) & (1 << i)) {
-                       imx_dmav1_writel(1 << i, DMA_DRTOSR);
-                       errcode |= IMX_DMA_ERR_REQUEST;
-               }
-               if (imx_dmav1_readl(DMA_DSESR) & (1 << i)) {
-                       imx_dmav1_writel(1 << i, DMA_DSESR);
-                       errcode |= IMX_DMA_ERR_TRANSFER;
-               }
-               if (imx_dmav1_readl(DMA_DBOSR) & (1 << i)) {
-                       imx_dmav1_writel(1 << i, DMA_DBOSR);
-                       errcode |= IMX_DMA_ERR_BUFFER;
-               }
-               if (imxdma->name && imxdma->err_handler) {
-                       imxdma->err_handler(i, imxdma->data, errcode);
-                       continue;
-               }
-
-               imx_dma_channels[i].sg = NULL;
-
-               printk(KERN_WARNING
-                      "DMA timeout on channel %d (%s) -%s%s%s%s\n",
-                      i, imxdma->name,
-                      errcode & IMX_DMA_ERR_BURST ?    " burst" : "",
-                      errcode & IMX_DMA_ERR_REQUEST ?  " request" : "",
-                      errcode & IMX_DMA_ERR_TRANSFER ? " transfer" : "",
-                      errcode & IMX_DMA_ERR_BUFFER ?   " buffer" : "");
-       }
-       return IRQ_HANDLED;
-}
-
-static void dma_irq_handle_channel(int chno)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[chno];
-
-       if (!imxdma->name) {
-               /*
-                * IRQ for an unregistered DMA channel:
-                * let's clear the interrupts and disable it.
-                */
-               printk(KERN_WARNING
-                      "spurious IRQ for DMA channel %d\n", chno);
-               return;
-       }
-
-       if (imxdma->sg) {
-               u32 tmp;
-               struct scatterlist *current_sg = imxdma->sg;
-               imxdma->sg = sg_next(imxdma->sg);
-
-               if (imxdma->sg) {
-                       imx_dma_sg_next(chno, imxdma->sg);
-
-                       tmp = imx_dmav1_readl(DMA_CCR(chno));
-
-                       if (imx_dma_hw_chain(imxdma)) {
-                               /* FIXME: The timeout should probably be
-                                * configurable
-                                */
-                               mod_timer(&imxdma->watchdog,
-                                       jiffies + msecs_to_jiffies(500));
-
-                               tmp |= CCR_CEN | CCR_RPT | CCR_ACRPT;
-                               imx_dmav1_writel(tmp, DMA_CCR(chno));
-                       } else {
-                               imx_dmav1_writel(tmp & ~CCR_CEN, DMA_CCR(chno));
-                               tmp |= CCR_CEN;
-                       }
-
-                       imx_dmav1_writel(tmp, DMA_CCR(chno));
-
-                       if (imxdma->prog_handler)
-                               imxdma->prog_handler(chno, imxdma->data,
-                                               current_sg);
-
-                       return;
-               }
-
-               if (imx_dma_hw_chain(imxdma)) {
-                       del_timer(&imxdma->watchdog);
-                       return;
-               }
-       }
-
-       imx_dmav1_writel(0, DMA_CCR(chno));
-       imxdma->in_use = 0;
-       if (imxdma->irq_handler)
-               imxdma->irq_handler(chno, imxdma->data);
-}
-
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-{
-       int i, disr;
-
-       if (cpu_is_mx21() || cpu_is_mx27())
-               dma_err_handler(irq, dev_id);
-
-       disr = imx_dmav1_readl(DMA_DISR);
-
-       pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
-                    disr);
-
-       imx_dmav1_writel(disr, DMA_DISR);
-       for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-               if (disr & (1 << i))
-                       dma_irq_handle_channel(i);
-       }
-
-       return IRQ_HANDLED;
-}
-
-/**
- * imx_dma_request - request/allocate specified channel number
- * @channel: i.MX DMA channel number
- * @name: the driver/caller own non-%NULL identification
- */
-int imx_dma_request(int channel, const char *name)
-{
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-       unsigned long flags;
-       int ret = 0;
-
-       /* basic sanity checks */
-       if (!name)
-               return -EINVAL;
-
-       if (channel >= IMX_DMA_CHANNELS) {
-               printk(KERN_CRIT "%s: called for  non-existed channel %d\n",
-                      __func__, channel);
-               return -EINVAL;
-       }
-
-       local_irq_save(flags);
-       if (imxdma->name) {
-               local_irq_restore(flags);
-               return -EBUSY;
-       }
-       memset(imxdma, 0, sizeof(*imxdma));
-       imxdma->name = name;
-       local_irq_restore(flags); /* request_irq() can block */
-
-       if (cpu_is_mx21() || cpu_is_mx27()) {
-               ret = request_irq(MX2x_INT_DMACH0 + channel,
-                               dma_irq_handler, 0, "DMA", NULL);
-               if (ret) {
-                       imxdma->name = NULL;
-                       pr_crit("Can't register IRQ %d for DMA channel %d\n",
-                                       MX2x_INT_DMACH0 + channel, channel);
-                       return ret;
-               }
-               init_timer(&imxdma->watchdog);
-               imxdma->watchdog.function = &imx_dma_watchdog;
-               imxdma->watchdog.data = channel;
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(imx_dma_request);
-
-/**
- * imx_dma_free - release previously acquired channel
- * @channel: i.MX DMA channel number
- */
-void imx_dma_free(int channel)
-{
-       unsigned long flags;
-       struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
-
-       if (!imxdma->name) {
-               printk(KERN_CRIT
-                      "%s: trying to free free channel %d\n",
-                      __func__, channel);
-               return;
-       }
-
-       local_irq_save(flags);
-       /* Disable interrupts */
-       imx_dma_disable(channel);
-       imxdma->name = NULL;
-
-       if (cpu_is_mx21() || cpu_is_mx27())
-               free_irq(MX2x_INT_DMACH0 + channel, NULL);
-
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(imx_dma_free);
-
-/**
- * imx_dma_request_by_prio - find and request some of free channels best
- * suiting requested priority
- * @channel: i.MX DMA channel number
- * @name: the driver/caller own non-%NULL identification
- *
- * This function tries to find a free channel in the specified priority group
- * if the priority cannot be achieved it tries to look for free channel
- * in the higher and then even lower priority groups.
- *
- * Return value: If there is no free channel to allocate, -%ENODEV is returned.
- *               On successful allocation channel is returned.
- */
-int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio)
-{
-       int i;
-       int best;
-
-       switch (prio) {
-       case (DMA_PRIO_HIGH):
-               best = 8;
-               break;
-       case (DMA_PRIO_MEDIUM):
-               best = 4;
-               break;
-       case (DMA_PRIO_LOW):
-       default:
-               best = 0;
-               break;
-       }
-
-       for (i = best; i < IMX_DMA_CHANNELS; i++)
-               if (!imx_dma_request(i, name))
-                       return i;
-
-       for (i = best - 1; i >= 0; i--)
-               if (!imx_dma_request(i, name))
-                       return i;
-
-       printk(KERN_ERR "%s: no free DMA channel found\n", __func__);
-
-       return -ENODEV;
-}
-EXPORT_SYMBOL(imx_dma_request_by_prio);
-
-static int __init imx_dma_init(void)
-{
-       int ret = 0;
-       int i;
-
-       if (cpu_is_mx1())
-               imx_dmav1_baseaddr = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
-       else if (cpu_is_mx21())
-               imx_dmav1_baseaddr = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
-       else if (cpu_is_mx27())
-               imx_dmav1_baseaddr = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
-       else
-               return 0;
-
-       dma_clk = clk_get(NULL, "dma");
-       if (IS_ERR(dma_clk))
-               return PTR_ERR(dma_clk);
-       clk_enable(dma_clk);
-
-       /* reset DMA module */
-       imx_dmav1_writel(DCR_DRST, DMA_DCR);
-
-       if (cpu_is_mx1()) {
-               ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", NULL);
-               if (ret) {
-                       pr_crit("Wow!  Can't register IRQ for DMA\n");
-                       return ret;
-               }
-
-               ret = request_irq(MX1_DMA_ERR, dma_err_handler, 0, "DMA", NULL);
-               if (ret) {
-                       pr_crit("Wow!  Can't register ERRIRQ for DMA\n");
-                       free_irq(MX1_DMA_INT, NULL);
-                       return ret;
-               }
-       }
-
-       /* enable DMA module */
-       imx_dmav1_writel(DCR_DEN, DMA_DCR);
-
-       /* clear all interrupts */
-       imx_dmav1_writel((1 << IMX_DMA_CHANNELS) - 1, DMA_DISR);
-
-       /* disable interrupts */
-       imx_dmav1_writel((1 << IMX_DMA_CHANNELS) - 1, DMA_DIMR);
-
-       for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-               imx_dma_channels[i].sg = NULL;
-               imx_dma_channels[i].dma_num = i;
-       }
-
-       return ret;
-}
-
-arch_initcall(imx_dma_init);
diff --git a/arch/arm/mach-imx/include/mach/dma-v1.h b/arch/arm/mach-imx/include/mach/dma-v1.h
deleted file mode 100644 (file)
index ac6fd71..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *  linux/arch/arm/mach-imx/include/mach/dma-v1.h
- *
- *  i.MX DMA registration and IRQ dispatching
- *
- * Copyright 2006 Pavel Pisa <pisa@cmp.felk.cvut.cz>
- * Copyright 2008 Juergen Beisert, <kernel@pengutronix.de>
- * Copyright 2008 Sascha Hauer, <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __MACH_DMA_V1_H__
-#define __MACH_DMA_V1_H__
-
-#define imx_has_dma_v1()       (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
-
-#include <mach/dma.h>
-
-#define IMX_DMA_CHANNELS  16
-
-#define DMA_MODE_READ          0
-#define DMA_MODE_WRITE         1
-#define DMA_MODE_MASK          1
-
-#define MX1_DMA_REG(offset)    MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR + (offset))
-
-/* DMA Interrupt Mask Register */
-#define MX1_DMA_DIMR           MX1_DMA_REG(0x08)
-
-/* Channel Control Register */
-#define MX1_DMA_CCR(x)         MX1_DMA_REG(0x8c + ((x) << 6))
-
-#define IMX_DMA_MEMSIZE_32     (0 << 4)
-#define IMX_DMA_MEMSIZE_8      (1 << 4)
-#define IMX_DMA_MEMSIZE_16     (2 << 4)
-#define IMX_DMA_TYPE_LINEAR    (0 << 10)
-#define IMX_DMA_TYPE_2D                (1 << 10)
-#define IMX_DMA_TYPE_FIFO      (2 << 10)
-
-#define IMX_DMA_ERR_BURST     (1 << 0)
-#define IMX_DMA_ERR_REQUEST   (1 << 1)
-#define IMX_DMA_ERR_TRANSFER  (1 << 2)
-#define IMX_DMA_ERR_BUFFER    (1 << 3)
-#define IMX_DMA_ERR_TIMEOUT   (1 << 4)
-
-int
-imx_dma_config_channel(int channel, unsigned int config_port,
-       unsigned int config_mem, unsigned int dmareq, int hw_chaining);
-
-void
-imx_dma_config_burstlen(int channel, unsigned int burstlen);
-
-int
-imx_dma_setup_single(int channel, dma_addr_t dma_address,
-               unsigned int dma_length, unsigned int dev_addr,
-               unsigned int dmamode);
-
-
-/*
- * Use this flag as the dma_length argument to imx_dma_setup_sg()
- * to create an endless running dma loop. The end of the scatterlist
- * must be linked to the beginning for this to work.
- */
-#define IMX_DMA_LENGTH_LOOP    ((unsigned int)-1)
-
-int
-imx_dma_setup_sg(int channel, struct scatterlist *sg,
-               unsigned int sgcount, unsigned int dma_length,
-               unsigned int dev_addr, unsigned int dmamode);
-
-int
-imx_dma_setup_handlers(int channel,
-               void (*irq_handler) (int, void *),
-               void (*err_handler) (int, void *, int), void *data);
-
-int
-imx_dma_setup_progression_handler(int channel,
-               void (*prog_handler) (int, void*, struct scatterlist*));
-
-void imx_dma_enable(int channel);
-
-void imx_dma_disable(int channel);
-
-int imx_dma_request(int channel, const char *name);
-
-void imx_dma_free(int channel);
-
-int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio);
-
-#endif /* __MACH_DMA_V1_H__ */
index 7696dfa2bdbabad8eb3280b9be8f8077eaa822aa..da6c1d9af7686868a8a7308310b59fd1dff5db00 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
+#include <asm/system_misc.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 
index 3a5ed2dd885af8326e42d63ba44e1a6a4caee39b..586e9f82212400555e42dca1b00492bf0c076b16 100644 (file)
@@ -33,6 +33,7 @@
 #include <mach/iomux-mx51.h>
 
 #include <asm/setup.h>
+#include <asm/system_info.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
index ea5f65b0381ae995ee7558793f4eba0e56e0697e..24aded9e109f09cd9d6e9c89304e0fa3c0d4f629 100644 (file)
@@ -36,6 +36,7 @@
 #include <mach/iomux-mx51.h>
 
 #include <asm/setup.h>
+#include <asm/system_info.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
index f8ca96c354f2280aa1ba10af200b3e443fce51fb..d534d7f988e0952f0d555c797c3620ff3b40ca1a 100644 (file)
@@ -61,8 +61,8 @@ static void imx3_idle(void)
                : "=r" (reg));
 }
 
-static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
-                                 unsigned int mtype)
+static void __iomem *imx3_ioremap_caller(unsigned long phys_addr, size_t size,
+                                        unsigned int mtype, void *caller)
 {
        if (mtype == MT_DEVICE) {
                /*
@@ -75,7 +75,7 @@ static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
                        mtype = MT_DEVICE_NONSHARED;
        }
 
-       return __arm_ioremap(phys_addr, size, mtype);
+       return __arm_ioremap_caller(phys_addr, size, mtype, caller);
 }
 
 void __init imx3_init_l2x0(void)
@@ -134,7 +134,7 @@ void __init imx31_init_early(void)
 {
        mxc_set_cpu_type(MXC_CPU_MX31);
        mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-       imx_ioremap = imx3_ioremap;
+       arch_ioremap_caller = imx3_ioremap_caller;
        arm_pm_idle = imx3_idle;
 }
 
@@ -208,7 +208,7 @@ void __init imx35_init_early(void)
        mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
        mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
        arm_pm_idle = imx3_idle;
-       imx_ioremap = imx3_ioremap;
+       arch_ioremap_caller = imx3_ioremap_caller;
 }
 
 void __init mx35_init_irq(void)
index 15b87f26ac963567f396532055eccbae42af15b1..eaf6c6366ffa0c7cac50a5c4e33715c8a2626afa 100644 (file)
@@ -25,9 +25,9 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/irq.h>
 #include <mach/cm.h>
-#include <asm/system.h>
+#include <mach/irqs.h>
+
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
index 37beed3fa3ed38a811faea3e96886f046abef737..8de70de3dd0a3fd57b3de3aa2ee0a862098eb916 100644 (file)
@@ -29,6 +29,5 @@
 #define PCI_IO_VADDR            0xee000000
 
 #define __io(a)                        ((void __iomem *)(PCI_IO_VADDR + (a)))
-#define __mem_pci(a)           (a)
 
 #endif
index 1fbe6d1902226a0d19bc796ef9048720a2853c9b..a19a1a2fcf6bece62d342599548286dae08aace4 100644 (file)
@@ -78,5 +78,6 @@
 #define IRQ_SIC_CP_LMINT7              46
 #define IRQ_SIC_END                    46
 
-#define NR_IRQS                         47
+#define NR_IRQS_INTEGRATOR_AP          34
+#define NR_IRQS_INTEGRATOR_CP          47
 
index 21a1d6cbef40c43dad90ff3fc9da70d550f78fe9..871f148ffd723fdb4389e7fff95f7b0d47494cea 100644 (file)
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/hardware/arm_timer.h>
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/param.h>         /* HZ */
 #include <asm/mach-types.h>
+#include <asm/sched_clock.h>
 
 #include <mach/lm.h>
+#include <mach/irqs.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -325,6 +326,11 @@ static void __init ap_init(void)
 
 static unsigned long timer_reload;
 
+static u32 notrace integrator_read_sched_clock(void)
+{
+       return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
+}
+
 static void integrator_clocksource_init(unsigned long inrate)
 {
        void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
@@ -341,6 +347,7 @@ static void integrator_clocksource_init(unsigned long inrate)
 
        clocksource_mmio_init(base + TIMER_VALUE, "timer2",
                        rate, 200, 16, clocksource_mmio_readl_down);
+       setup_sched_clock(integrator_read_sched_clock, 16, rate);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
@@ -468,6 +475,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
        .atag_offset    = 0x100,
        .reserve        = integrator_reserve,
        .map_io         = ap_map_io,
+       .nr_irqs        = NR_IRQS_INTEGRATOR_AP,
        .init_early     = integrator_init_early,
        .init_irq       = ap_init_irq,
        .timer          = &ap_timer,
index be9ead4a3bcc3b55a44634fbdc6eabcb37733a32..48a115a91d9d1c3a2bb479dc00bedefe257ceb5c 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/arm_timer.h>
@@ -34,6 +33,7 @@
 
 #include <mach/cm.h>
 #include <mach/lm.h>
+#include <mach/irqs.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -464,6 +464,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
        .atag_offset    = 0x100,
        .reserve        = integrator_reserve,
        .map_io         = intcp_map_io,
+       .nr_irqs        = NR_IRQS_INTEGRATOR_CP,
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq,
        .timer          = &cp_timer,
index 28be186adb89fea5256016be198be87de4d10ac1..466defa97842944171ef7fab1c8c151805291772 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 #include <mach/cm.h>
 
index 520b6bf81bb1c5ebb0a671700ad5fe40686307e4..f1ca9c122861ba468ec2bc507a2e7a48050d15aa 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
-#include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include <mach/irqs.h>
+
 /* 
  * A small note about bridges and interrupts.  The DECchip 21050 (and
  * later) adheres to the PCI-PCI bridge specification.  This says that
index 015be770c1d87e04261e0d62ebec3a07ec548b40..67e6f9a9d1a0962e8f64f4b09e1582a35d6bcad2 100644 (file)
@@ -30,9 +30,9 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/irq.h>
+#include <mach/irqs.h>
+
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/irq_regs.h>
 
index dffb234bb967ec9b3e76384a8c9af699747dea12..f13188518025f07515082189e767772828763a3b 100644 (file)
 #define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(a) __iop13xx_io(a)
-#define __mem_pci(a) (a)
-#define __mem_isa(a) (a)
 
 extern void __iomem * __iop13xx_io(unsigned long io_addr);
-extern void __iomem *__iop13xx_ioremap(unsigned long cookie, size_t size,
-       unsigned int mtype);
-extern void __iop13xx_iounmap(void __iomem *addr);
-
-extern u32 iop13xx_atue_mem_base;
-extern u32 iop13xx_atux_mem_base;
-extern size_t iop13xx_atue_mem_size;
-extern size_t iop13xx_atux_mem_size;
-
-#define __arch_ioremap __iop13xx_ioremap
-#define __arch_iounmap __iop13xx_iounmap
 
 #endif
index 07e9ff7adafb4dd5c79f2b6ba83fb785ed03186d..e190dcd7d72dc1afd69adb2d637ef6630c3af855 100644 (file)
@@ -5,6 +5,7 @@
 /* The ATU offsets can change based on the strapping */
 extern u32 iop13xx_atux_pmmr_offset;
 extern u32 iop13xx_atue_pmmr_offset;
+void iop13xx_init_early(void);
 void iop13xx_init_irq(void);
 void iop13xx_map_io(void);
 void iop13xx_platform_init(void);
index 48642e66c5663007129db7bec7cd909e6749fa49..3c364198db9c91a9b611df556c5b08db35a74038 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/io.h>
 #include <mach/hardware.h>
 
+#include "pci.h"
+
 void * __iomem __iop13xx_io(unsigned long io_addr)
 {
        void __iomem * io_virt;
@@ -40,8 +42,8 @@ void * __iomem __iop13xx_io(unsigned long io_addr)
 }
 EXPORT_SYMBOL(__iop13xx_io);
 
-void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
-       unsigned int mtype)
+static void __iomem *__iop13xx_ioremap_caller(unsigned long cookie,
+       size_t size, unsigned int mtype, void *caller)
 {
        void __iomem * retval;
 
@@ -76,17 +78,14 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
                break;
        default:
                retval = __arm_ioremap_caller(cookie, size, mtype,
-                               __builtin_return_address(0));
+                               caller);
        }
 
        return retval;
 }
-EXPORT_SYMBOL(__iop13xx_ioremap);
 
-void __iop13xx_iounmap(void __iomem *addr)
+static void __iop13xx_iounmap(volatile void __iomem *addr)
 {
-       extern void __iounmap(volatile void __iomem *addr);
-
        if (iop13xx_atue_mem_base)
                if (addr >= (void __iomem *) iop13xx_atue_mem_base &&
                    addr < (void __iomem *) (iop13xx_atue_mem_base +
@@ -110,4 +109,9 @@ void __iop13xx_iounmap(void __iomem *addr)
 skip:
        return;
 }
-EXPORT_SYMBOL(__iop13xx_iounmap);
+
+void __init iop13xx_init_early(void)
+{
+       arch_ioremap_caller = __iop13xx_ioremap_caller;
+       arch_iounmap = __iop13xx_iounmap;
+}
index abaee883358874f4bbaf5c5bf1c7a6a90bf6bf2a..5c96b73e6964c42de4fba7efd00d2c0a932dd827 100644 (file)
@@ -92,6 +92,7 @@ static struct sys_timer iq81340mc_timer = {
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
        .atag_offset    = 0x100,
+       .init_early     = iop13xx_init_early,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
        .timer          = &iq81340mc_timer,
index 690916a09dc6bed10561272d8e300f5838bbb76b..aa4dd750135abc64e15e6fd0787f54aadf32d3ad 100644 (file)
@@ -94,6 +94,7 @@ static struct sys_timer iq81340sc_timer = {
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
        .atag_offset    = 0x100,
+       .init_early     = iop13xx_init_early,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
        .timer          = &iq81340sc_timer,
diff --git a/arch/arm/mach-iop13xx/pci.h b/arch/arm/mach-iop13xx/pci.h
new file mode 100644 (file)
index 0000000..c70cf5b
--- /dev/null
@@ -0,0 +1,6 @@
+#include <linux/types.h>
+
+extern u32 iop13xx_atue_mem_base;
+extern u32 iop13xx_atux_mem_base;
+extern size_t iop13xx_atue_mem_size;
+extern size_t iop13xx_atux_mem_size;
index 2d88264b9863b36de1c4d837aafb2cb2a9941693..e2ada265bb8d0d498b6c90b66f67c02281f67af8 100644 (file)
@@ -15,6 +15,5 @@
 
 #define IO_SPACE_LIMIT         0xffffffff
 #define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
-#define __mem_pci(a)           (a)
 
 #endif
index a8a66fc8fbdbe8eb5ac34c3a5b08583caa1d3de7..f7c1b6595660bc6f8cfb33bf9c9a440b4b4f8c26 100644 (file)
@@ -15,6 +15,5 @@
 
 #define IO_SPACE_LIMIT         0xffffffff
 #define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
-#define __mem_pci(a)           (a)
 
 #endif
index cdae24e46eeae784398f3674973157ece4b6a434..bbf54d794ce81edf74ce922e37285780d3139850 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/hardware/iop3xx.h>
index 81c45370a4e6f4c63b0854d0e41fa5ec79ec54f8..f214cdff01cb8511afd6a291094d798710acf2c1 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index e872d238cd0fd36103f29581544404c3a08de098..4867f408617c0123ac7a289e0613272efca1bd7a 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index 859e584914d98072c7b06870be2ec8f914d29392..f6552d6f35ab193e5771db6a2c9b5d5a2a10737c 100644 (file)
@@ -18,7 +18,6 @@
 #include <mach/hardware.h>
 
 #define IO_SPACE_LIMIT         0xffffffff
-#define __mem_pci(a)           (a)
 
 /*
  * The A? revisions of the IXP2000s assert byte lanes for PCI I/O
index d519944653adb32c544874c0266049851abfb8db..915ad49e3b8fdf0d918523f8ee35b2c0ef4549a9 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index b415febd2025fcf0022547d8bbea57b388b06bfc..a9f1819ea04900315bfd3872141def00b27dfde7 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index dd9838299068266e3315c5fbd21c302834fabf0d..421e38dc0facabe217fc3f663dfd382336e97a1f 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index 7632beadabf6ac7c9ac656ee9d853b0755e5eb60..5196c39cdba4ac82d95882a345dfdc5c87620ce2 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index 49c36f3cd602c551be909d48a1b3f78a11616dfa..9c02de932facfbf3f947ed414a9430eb2cb51f86 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 
 #include <asm/mach/pci.h>
index 7c1495e4fe7abeabc9379f9bd022b3460dfd45ec..d2c2dc35cbdd7132d935fcf80ae321da3dbf3db1 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 8f2487e1fc4e1a7e0a2fe5ba3abd554a7ea83810..d142d45dea124a724004eed225337eed2c481fba 100644 (file)
@@ -32,7 +32,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 4ce4353b9f72d144ba07febbd6f56a3f557407cd..a7aceb55c1306dc66341b0adf50ecd27401a9815 100644 (file)
@@ -18,6 +18,5 @@
 #define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(p)                ((void __iomem*)((p) + IXP23XX_PCI_IO_VIRT))
-#define __mem_pci(a)   (a)
 
 #endif
index 5d5dd3e8d0693fda41ed7667b2476b890b375678..b0e07db5ceaf2416d79606f4dca8e19d41f290d1 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 3cbbd3208fa8994dafc8c5247d49924921aa36a7..911f5a58e0068edb238a283adc3365232acca976 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <asm/irq.h>
 #include <asm/sizes.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <mach/hardware.h>
 
index 377283fc658cd8944ffa19def4ab370f02b7c0c9..eaaa3fa9fd05f2ccb4de0ede9a0f64700b1be33d 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index a7277ad470a50ffdf8248f1b574b9961dccea0ca..90e42e9982cb1031d9bdc53a0c9b032a3bc6e5ec 100644 (file)
@@ -165,6 +165,7 @@ static void __init avila_init(void)
 MACHINE_START(AVILA, "Gateworks Avila Network Platform")
        /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
@@ -184,6 +185,7 @@ MACHINE_END
 MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
        /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index 8508882b13f0303c36d2f39edf043097c05c1961..d5719eb425913e91dde8216d2dfa408a644bf2d4 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/cputype.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <mach/hardware.h>
 
index a6329a0a8ec4b3dc0522df2bc130e683cd171f5a..c60e7b86192c90dffd028f4b14bc1dae82a96c31 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/udc.h>
 #include <mach/hardware.h>
+#include <mach/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -517,3 +518,35 @@ void ixp4xx_restart(char mode, const char *cmd)
                *IXP4XX_OSWE = IXP4XX_WDT_RESET_ENABLE | IXP4XX_WDT_COUNT_ENABLE;
        }
 }
+
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+/*
+ * In the case of using indirect PCI, we simply return the actual PCI
+ * address and our read/write implementation use that to drive the
+ * access registers. If something outside of PCI is ioremap'd, we
+ * fallback to the default.
+ */
+
+static void __iomem *ixp4xx_ioremap_caller(unsigned long addr, size_t size,
+                                          unsigned int mtype, void *caller)
+{
+       if (!is_pci_memory(addr))
+               return __arm_ioremap_caller(addr, size, mtype, caller);
+
+       return (void __iomem *)addr;
+}
+
+static void ixp4xx_iounmap(void __iomem *addr)
+{
+       if (!is_pci_memory((__force u32)addr))
+               __iounmap(addr);
+}
+
+void __init ixp4xx_init_early(void)
+{
+       arch_ioremap_caller = ixp4xx_ioremap_caller;
+       arch_iounmap = ixp4xx_iounmap;
+}
+#else
+void __init ixp4xx_init_early(void) {}
+#endif
index a74f86ce8bcc8252576215455998b79fb7b5d1a6..1b83110028d6d95f1c99e7a4e42e03ee0b987985 100644 (file)
@@ -110,6 +110,7 @@ static void __init coyote_init(void)
 MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
        /* Maintainer: MontaVista Software, Inc. */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
@@ -129,6 +130,7 @@ MACHINE_END
 MACHINE_START(IXDPG425, "Intel IXDPG425")
        /* Maintainer: MontaVista Software, Inc. */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index 67be177b336aa0ebd04315f31bc659d66c8c65f8..97a0af8f1955da9b83f5be0fca9014ffc6315aa8 100644 (file)
@@ -280,6 +280,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
        /* Maintainer: www.nslu2-linux.org */
        .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &dsmg600_timer,
        .init_machine   = dsmg600_init,
index 6d5818285af8efd970d363aff1cee67003d7d281..9175a25a7511723d5a4de4f2d1d4a21b21f74a86 100644 (file)
@@ -270,6 +270,7 @@ static void __init fsg_init(void)
 MACHINE_START(FSG, "Freecom FSG-3")
        /* Maintainer: www.nslu2-linux.org */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index 7ecf9b28f1c0a3d0d8c2f288e94cf2a18bf6ee14..033c7175895393f82524be3d04d77327858804e8 100644 (file)
@@ -97,6 +97,7 @@ static void __init gateway7001_init(void)
 MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
        /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index c0e3d69a8aeccf23e7372693c01284b9d43e6917..46bb924962ee41f15e8340513b8e2974a9083216 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/pci.h>
@@ -497,6 +496,7 @@ subsys_initcall(gmlr_pci_init);
 MACHINE_START(GORAMO_MLR, "MultiLink")
        /* Maintainer: Krzysztof Halasa */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index a23f8939145836b280a8fbd53d35b4dce0f45ad1..18ebc6be7969cf5f42ea17e4a531bc6ac2c5d43b 100644 (file)
@@ -165,6 +165,7 @@ static void __init gtwx5715_init(void)
 MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
        /* Maintainer: George Joseph */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index c30e7e923a73a2337b9a68de6eeea2cf1a39b0a0..034bb2a1b805333829aee38fe89ba7d4797826d0 100644 (file)
@@ -23,8 +23,6 @@
 #define PCIBIOS_MAX_MEM                0x4BFFFFFF
 #endif
 
-#define ARCH_HAS_DMA_SET_COHERENT_MASK
-
 /* Register locations and bits */
 #include "ixp4xx-regs.h"
 
index ffb9d6afb89f4dfd789ec03a6ccaabf6b4dea61d..5cf30d1b78d22b8901865f0426efefcc09d2a9c1 100644 (file)
@@ -39,11 +39,7 @@ extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
  *    but in some cases the performance hit is acceptable. In addition, you
  *    cannot mmap() PCI devices in this case.
  */
-#ifndef        CONFIG_IXP4XX_INDIRECT_PCI
-
-#define __mem_pci(a)           (a)
-
-#else
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
 
 /*
  * In the case of using indirect PCI, we simply return the actual PCI
@@ -57,24 +53,6 @@ static inline int is_pci_memory(u32 addr)
        return (addr >= PCIBIOS_MIN_MEM) && (addr <= 0x4FFFFFFF);
 }
 
-static inline void __iomem * __indirect_ioremap(unsigned long addr, size_t size,
-                                               unsigned int mtype)
-{
-       if (!is_pci_memory(addr))
-               return __arm_ioremap(addr, size, mtype);
-
-       return (void __iomem *)addr;
-}
-
-static inline void __indirect_iounmap(void __iomem *addr)
-{
-       if (!is_pci_memory((__force u32)addr))
-               __iounmap(addr);
-}
-
-#define __arch_ioremap                 __indirect_ioremap
-#define __arch_iounmap                 __indirect_iounmap
-
 #define writeb(v, p)                   __indirect_writeb(v, p)
 #define writew(v, p)                   __indirect_writew(v, p)
 #define writel(v, p)                   __indirect_writel(v, p)
index df9250bbf13d90c1b198338ae61be5366b0041c8..b66bedc64de175154f660d47bbd3ab34700cea34 100644 (file)
@@ -121,6 +121,7 @@ extern unsigned long ixp4xx_timer_freq;
  * Functions used by platform-level setup code
  */
 extern void ixp4xx_map_io(void);
+extern void ixp4xx_init_early(void);
 extern void ixp4xx_init_irq(void);
 extern void ixp4xx_sys_init(void);
 extern void ixp4xx_timer_init(void);
index 8a38b39999f836b5ffb7c3f430ce8f489eb7b8a5..3d742aee177304250d78aa775d69475364a94866 100644 (file)
@@ -254,6 +254,7 @@ static void __init ixdp425_init(void)
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
@@ -269,6 +270,7 @@ MACHINE_END
 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
@@ -283,6 +285,7 @@ MACHINE_END
 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
@@ -297,6 +300,7 @@ MACHINE_END
 MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
        /* Maintainer: MontaVista Software, Inc. */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index 1010eb7b0083c6a0f33a63fe373d9567c9ea5b7a..33cb0955b6bffa840b2ae727e7ea76753803aa4b 100644 (file)
@@ -315,6 +315,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d")
        /* Maintainer: www.nslu2-linux.org */
        .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .init_machine   = nas100d_init,
index aa355c360d5720e4665999f4acfa11e9495d2467..e2903faaebb35f4ffc4ddfcb0c08f53046e05033 100644 (file)
@@ -301,6 +301,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2")
        /* Maintainer: www.nslu2-linux.org */
        .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &nslu2_timer,
        .init_machine   = nslu2_init,
index 0940869fcfdd33f487c629806b65862433a2c5c4..158ddb79821da36168bb9c00a1e711bf5c17286a 100644 (file)
@@ -243,6 +243,7 @@ static void __init omixp_init(void)
 MACHINE_START(DEVIXP, "Omicron DEVIXP")
        .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .init_machine   = omixp_init,
@@ -254,6 +255,7 @@ MACHINE_END
 MACHINE_START(MICCPT, "Omicron MICCPT")
        .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .init_machine   = omixp_init,
@@ -268,6 +270,7 @@ MACHINE_END
 MACHINE_START(MIC256, "Omicron MIC256")
        .atag_offset    = 0x100,
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .init_machine   = omixp_init,
index 9dec20683291f4eb3c4ee4874b6046bd70788c38..2798f435aaf4fbf3f24eb56fca8851e3decfc985 100644 (file)
@@ -237,6 +237,7 @@ static void __init vulcan_init(void)
 MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index 5ac0f0a0fd8cea97f30046de24fffcebb190a784..a785175b115bf146f1e96ef13d41f0408897e514 100644 (file)
@@ -98,6 +98,7 @@ static void __init wg302v2_init(void)
 MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
        /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
        .map_io         = ixp4xx_map_io,
+       .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
        .timer          = &ixp4xx_timer,
        .atag_offset    = 0x100,
index 49dd0cb5e16621818a49c52ff529b9b7b18df5f4..5d0ab61700d2a1519acc0fdcefe8def46bdf7c02 100644 (file)
@@ -20,7 +20,5 @@ static inline void __iomem *__io(unsigned long addr)
 }
 
 #define __io(a)                        __io(a)
-#define __mem_pci(a)           (a)
-
 
 #endif
diff --git a/arch/arm/mach-ks8695/include/mach/io.h b/arch/arm/mach-ks8695/include/mach/io.h
deleted file mode 100644 (file)
index a7a63ac..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/io.h
- *
- * Copyright (C) 2006 Andrew Victor
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT         0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 37dfcd5bd2ad9178213bac8ad27b080cd37dc03d..ec783a3070aedc3ae6d83d1a44d1bb4c68491a3e 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/time.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-timer.h>
 #include <mach/regs-irq.h>
diff --git a/arch/arm/mach-lpc32xx/include/mach/io.h b/arch/arm/mach-lpc32xx/include/mach/io.h
deleted file mode 100644 (file)
index 9b59ab5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/io.h
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 3588a55841532f4dc0c6c5268ec87b0e0c40319a..bf5d8e195c3efb03849660ffac3d923897e88b33 100644 (file)
@@ -23,6 +23,7 @@
 #include <mach/addr-map.h>
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
+#include <mach/irqs.h>
 #include <video/pxa168fb.h>
 #include <linux/input.h>
 #include <plat/pxa27x_keypad.h>
@@ -239,7 +240,7 @@ static void __init common_init(void)
 
 MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = common_init,
@@ -248,7 +249,7 @@ MACHINE_END
 
 MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = common_init,
index b148a9dc5a443a5e19987ba9a46b66c4fe043d71..603542ae6fbd61e6696cad9eef7424f82fb90cca 100644 (file)
@@ -43,6 +43,7 @@ static void __init avengers_lite_init(void)
 
 MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
        .map_io         = mmp_map_io,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = avengers_lite_init,
index d839fe6421e69654468a3e3aaa22002cdb142076..5cb769cd26d9a470a62fca737dc6dffe0afa80ee 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "common.h"
 
-#define BROWNSTONE_NR_IRQS     (IRQ_BOARD_START + 40)
+#define BROWNSTONE_NR_IRQS     (MMP_NR_IRQS + 40)
 
 #define GPIO_5V_ENABLE         (89)
 
@@ -158,7 +158,7 @@ static struct platform_device brownstone_v_5vp_device = {
 };
 
 static struct max8925_platform_data brownstone_max8925_info = {
-       .irq_base               = IRQ_BOARD_START,
+       .irq_base               = MMP_NR_IRQS,
 };
 
 static struct i2c_board_info brownstone_twsi1_info[] = {
index 062b5b93c50e9eb2e8398f600de29d120a905289..9292b7966e3b7d993eeddd2c2a4906de52e8af9c 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/page.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/addr-map.h>
 #include <mach/cputype.h>
 
index 2ee8cd7829dd862ff0d062b52f56baeab12a1c7a..8059cc0905c6063e5dc079f9b03545d28d90bb5d 100644 (file)
 #include <mach/addr-map.h>
 #include <mach/mfp-mmp2.h>
 #include <mach/mmp2.h>
+#include <mach/irqs.h>
 
 #include "common.h"
 
-#define FLINT_NR_IRQS  (IRQ_BOARD_START + 48)
+#define FLINT_NR_IRQS  (MMP_NR_IRQS + 48)
 
 static unsigned long flint_pin_config[] __initdata = {
        /* UART1 */
index 87765467de633c896c00188906bb289c966dda68..f516e74ce0d5bf1ecc2b20fc874fae1c822c185e 100644 (file)
@@ -191,7 +191,7 @@ static void __init gplugd_init(void)
 
 MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = gplugd_init,
index 3e404acd6ff4d8af83944256026a7d0c11a419f3..b1ece08174e8bde11d5b8c8f48ab69673c04d3ae 100644 (file)
 #ifndef __ASM_MACH_ADDR_MAP_H
 #define __ASM_MACH_ADDR_MAP_H
 
-#ifndef __ASSEMBLER__
-#define IOMEM(x)       ((void __iomem *)(x))
-#else
-#define IOMEM(x)       (x)
-#endif
-
 /* APB - Application Subsystem Peripheral Bus
  *
  * NOTE: the DMA controller registers are actually on the AXI fabric #1
diff --git a/arch/arm/mach-mmp/include/mach/io.h b/arch/arm/mach-mmp/include/mach/io.h
deleted file mode 100644 (file)
index e7adf3d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/io.h
- *
- * 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.
- */
-
-#ifndef __ASM_MACH_IO_H
-#define __ASM_MACH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif /* __ASM_MACH_IO_H */
index 34635a0bbb5924be0db26ffa8a1ddfd12d65da71..d0e746626a3d895250268c301eaa6d2372c946be 100644 (file)
 #define MMP_GPIO_TO_IRQ(gpio)          (IRQ_GPIO_START + (gpio))
 
 #define IRQ_BOARD_START                        (IRQ_GPIO_START + MMP_NR_BUILTIN_GPIO)
-
-#define NR_IRQS                                (IRQ_BOARD_START)
+#define MMP_NR_IRQS                    IRQ_BOARD_START
 
 #endif /* __ASM_MACH_IRQS_H */
index d21c5441a3d0c7c8e0649376b4556d29b6e44cd5..7895d277421e74c225bfddcb76b19a8a7bd72e24 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <mach/irqs.h>
 #include <mach/regs-icu.h>
 #include <mach/mmp2.h>
 
index 96cf5c8fe47dcb3b0529ead1538281d584f47e13..ff73249884d031bb165b89d905411ffb65cd067c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mfd/max8925.h>
 #include <linux/interrupt.h>
 
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
@@ -27,7 +28,7 @@
 
 #include "common.h"
 
-#define JASPER_NR_IRQS         (IRQ_BOARD_START + 48)
+#define JASPER_NR_IRQS         (MMP_NR_IRQS + 48)
 
 static unsigned long jasper_pin_config[] __initdata = {
        /* UART1 */
@@ -135,7 +136,7 @@ static struct max8925_power_pdata jasper_power_data = {
 static struct max8925_platform_data jasper_max8925_info = {
        .backlight              = &jasper_backlight_data,
        .power                  = &jasper_power_data,
-       .irq_base               = IRQ_BOARD_START,
+       .irq_base               = MMP_NR_IRQS,
 };
 
 static struct i2c_board_info jasper_twsi1_info[] = {
index f7d59c03fc670c18b9c82a978d4a44eacce00019..b24d2c32cba984c1b72a3b2f20761c944d24ced5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/mach/time.h>
+#include <asm/system_misc.h>
 #include <mach/addr-map.h>
 #include <mach/cputype.h>
 #include <mach/regs-apbc.h>
index bc97170125bf6b410d04af230c2961d9739d2714..b28f9084dfff2e62bd57f6c0518c6320091d03ce 100644 (file)
@@ -101,6 +101,7 @@ static void __init tavorevb_init(void)
 
 MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
        .map_io         = mmp_map_io,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa910_init_irq,
        .timer          = &pxa910_timer,
        .init_machine   = tavorevb_init,
index 0523e422990eeb3f3e6cb98afab1a4d6ea62f049..42bef6674ecfdb2eb601553ff2267e7ad77a17fe 100644 (file)
@@ -26,6 +26,7 @@
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
 #include <mach/teton_bga.h>
+#include <mach/irqs.h>
 
 #include "common.h"
 
@@ -83,7 +84,7 @@ static void __init teton_bga_init(void)
 
 MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = teton_bga_init,
index e72c709da44f3e2461e6817c504ed571b909fecd..3fc9ed21f97d20d8c5a63a79b5dce8f0be05c1a9 100644 (file)
@@ -38,7 +38,7 @@
  * 16 board interrupts -- PCA9575 GPIO expander
  * 24 board interrupts -- 88PM860x PMIC
  */
-#define TTCDKB_NR_IRQS         (IRQ_BOARD_START + 16 + 16 + 24)
+#define TTCDKB_NR_IRQS         (MMP_NR_IRQS + 16 + 16 + 24)
 
 static unsigned long ttc_dkb_pin_config[] __initdata = {
        /* UART2 */
@@ -131,7 +131,7 @@ static struct platform_device *ttc_dkb_devices[] = {
 static struct pca953x_platform_data max7312_data[] = {
        {
                .gpio_base      = TTCDKB_GPIO_EXT0(0),
-               .irq_base       = IRQ_BOARD_START,
+               .irq_base       = MMP_NR_IRQS,
        },
 };
 
index a60ab6d04ec5927ef151b4e62162cdb8f11fffb1..3698a370d6360051f00cb02bbfc62cb861568e6d 100644 (file)
@@ -68,6 +68,11 @@ static struct platform_device *devices[] __initdata = {
 
 extern struct sys_timer msm_timer;
 
+static void __init halibut_init_early(void)
+{
+       arch_ioremap_caller = __msm_ioremap_caller;
+}
+
 static void __init halibut_init_irq(void)
 {
        msm_init_irq();
@@ -96,6 +101,7 @@ MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
        .atag_offset    = 0x100,
        .fixup          = halibut_fixup,
        .map_io         = halibut_map_io,
+       .init_early     = halibut_init_early,
        .init_irq       = halibut_init_irq,
        .init_machine   = halibut_init,
        .timer          = &msm_timer,
index 97b8191d9d385951efbc387550e3c9e606e96b81..4a8ea0d40b6ffe0b794d95a29f6d9e9003456eab 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
-#include <asm/system.h>
 #include <mach/system.h>
 #include <mach/vreg.h>
 #include <mach/board.h>
index 6b9b227c87c59e25108d5570b72a0ebbe1227d66..5414f76ec0a948578b6c2c28c2058acbb2ccf133 100644 (file)
@@ -43,6 +43,11 @@ static struct platform_device *devices[] __initdata = {
 
 extern struct sys_timer msm_timer;
 
+static void __init trout_init_early(void)
+{
+       arch_ioremap_caller = __msm_ioremap_caller;
+}
+
 static void __init trout_init_irq(void)
 {
        msm_init_irq();
@@ -96,6 +101,7 @@ MACHINE_START(TROUT, "HTC Dream")
        .atag_offset    = 0x100,
        .fixup          = trout_fixup,
        .map_io         = trout_map_io,
+       .init_early     = trout_init_early,
        .init_irq       = trout_init_irq,
        .init_machine   = trout_init,
        .timer          = &msm_timer,
diff --git a/arch/arm/mach-msm/include/mach/io.h b/arch/arm/mach-msm/include/mach/io.h
deleted file mode 100644 (file)
index dc1b928..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* arch/arm/mach-msm/include/mach/io.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __arch_ioremap __msm_ioremap
-#define __arch_iounmap __iounmap
-
-void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype);
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)    (a)
-
-void msm_map_qsd8x50_io(void);
-void msm_map_msm7x30_io(void);
-void msm_map_msm8x60_io(void);
-void msm_map_msm8960_io(void);
-
-extern unsigned int msm_shared_ram_phys;
-
-#endif
index 8af46123dab6856c3870e82ac519edf62eab5ad8..6c4046c21296c976e7352a8c260bf661be090324 100644 (file)
  *
  */
 
-#ifdef __ASSEMBLY__
-#define IOMEM(x)       x
-#else
-#define IOMEM(x)       ((void __force __iomem *)(x))
-#endif
-
 #define MSM_VIC_BASE          IOMEM(0xE0000000)
 #define MSM_VIC_PHYS          0xC0000000
 #define MSM_VIC_SIZE          SZ_4K
 #define MSM_AD5_PHYS          0xAC000000
 #define MSM_AD5_SIZE          (SZ_1M*13)
 
+#ifndef __ASSEMBLY__
+
+extern void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size,
+                                         unsigned int mtype, void *caller);
+
+#endif
 
 #endif
index 198202c267c846d6375be0f59bf2aad38eba277a..f944fe65a657c4847bbeadfa1a7973d4503ea1ca 100644 (file)
 #define MSM_HSUSB_PHYS        0xA3600000
 #define MSM_HSUSB_SIZE        SZ_1K
 
+#ifndef __ASSEMBLY__
+extern void msm_map_msm7x30_io(void);
+#endif
+
 #endif
index 800b55767e6b83ee7856692bf4e8fcf122df5863..a1752c0284fca2e25ebdd74d100c6442c8799b1c 100644 (file)
@@ -50,4 +50,8 @@
 #define MSM_DEBUG_UART_PHYS    0x16440000
 #endif
 
+#ifndef __ASSEMBLY__
+extern void msm_map_msm8960_io(void);
+#endif
+
 #endif
index 0faa894729b7737d2c310f890aa27bd339506ec8..da77cc1d545d0158949eda6c3042d57ff9e2566a 100644 (file)
 #define MSM_SDC4_PHYS          0xA0600000
 #define MSM_SDC4_SIZE          SZ_4K
 
+#ifndef __ASSEMBLY__
+extern void msm_map_qsd8x50_io(void);
+#endif
+
 #endif
index 54e12caa8d860a99a4d6c4e11505e25a7d269d62..5aed57dc808c081f13c99f5d6ed0883c4ba46b56 100644 (file)
@@ -67,4 +67,8 @@
 #define MSM_DEBUG_UART_PHYS    0x19C40000
 #endif
 
+#ifndef __ASSEMBLY__
+extern void msm_map_msm8x60_io(void);
+#endif
+
 #endif
index 90682f4599d3dd4842e18129781e949952e237ef..00afdfb8c38fe24eacc2d0c87709fe448b06eed0 100644 (file)
  *
  */
 
-#ifdef __ASSEMBLY__
-#define IOMEM(x)       x
-#else
-#define IOMEM(x)       ((void __force __iomem *)(x))
-#endif
-
 #if defined(CONFIG_ARCH_MSM7X30)
 #include "msm_iomap-7x30.h"
 #elif defined(CONFIG_ARCH_QSD8X50)
index 578b04e42deb8cbc1d29fa66b75fb20c3a21ff43..a1e7b11688500fb0e08040dbe4ddaf7f95f6eabf 100644 (file)
@@ -172,8 +172,8 @@ void __init msm_map_msm7x30_io(void)
 }
 #endif /* CONFIG_ARCH_MSM7X30 */
 
-void __iomem *
-__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
+void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size,
+                                  unsigned int mtype, void *caller)
 {
        if (mtype == MT_DEVICE) {
                /* The peripherals in the 88000000 - D0000000 range
@@ -184,7 +184,5 @@ __msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
                        mtype = MT_DEVICE_NONSHARED;
        }
 
-       return __arm_ioremap_caller(phys_addr, size, mtype,
-               __builtin_return_address(0));
+       return __arm_ioremap_caller(phys_addr, size, mtype, caller);
 }
-EXPORT_SYMBOL(__msm_ioremap);
index 75f4be40b3e5d8f8ed98ab87e33282b685009999..812808254936575efb06902de9b4bbe7d4941084 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/mach/time.h>
 #include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
+#include <asm/sched_clock.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/cpu.h>
@@ -105,12 +106,12 @@ static union {
 
 static void __iomem *source_base;
 
-static cycle_t msm_read_timer_count(struct clocksource *cs)
+static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
 {
        return readl_relaxed(source_base + TIMER_COUNT_VAL);
 }
 
-static cycle_t msm_read_timer_count_shift(struct clocksource *cs)
+static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
 {
        /*
         * Shift timer count down by a constant due to unreliable lower bits
@@ -166,6 +167,11 @@ static struct local_timer_ops msm_local_timer_ops __cpuinitdata = {
 };
 #endif /* CONFIG_LOCAL_TIMERS */
 
+static notrace u32 msm_sched_clock_read(void)
+{
+       return msm_clocksource.read(&msm_clocksource);
+}
+
 static void __init msm_timer_init(void)
 {
        struct clock_event_device *ce = &msm_clockevent;
@@ -232,6 +238,8 @@ err:
        res = clocksource_register_hz(cs, dgt_hz);
        if (res)
                pr_err("clocksource_register failed\n");
+       setup_sched_clock(msm_sched_clock_read,
+                       cpu_is_msm7x01() ? 32 - MSM_DGT_SHIFT : 32, dgt_hz);
 }
 
 struct sys_timer msm_timer = {
index 450e0e1ad0920df19f330cf4c0898e6e385035e1..c7d9d00d8fc17ad1a3e2cba71343d02639afe5ee 100644 (file)
@@ -20,7 +20,5 @@ static inline void __iomem *__io(unsigned long addr)
 }
 
 #define __io(a)                        __io(a)
-#define __mem_pci(a)           (a)
-
 
 #endif
index 53e89a09bf0d9fae62e8721ace3047ba346803bc..4c0e8a64d8c74559d80d0d4b586bf5d977b64b4a 100644 (file)
 #ifndef __MACH_MXS_HARDWARE_H__
 #define __MACH_MXS_HARDWARE_H__
 
-#ifdef __ASSEMBLER__
-#define IOMEM(addr)    (addr)
-#else
-#define IOMEM(addr)    ((void __force __iomem *)(addr))
-#endif
-
 #endif /* __MACH_MXS_HARDWARE_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/io.h b/arch/arm/mach-mxs/include/mach/io.h
deleted file mode 100644 (file)
index 289b722..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __MACH_MXS_IO_H__
-#define __MACH_MXS_IO_H__
-
-/* Allow IO space to be anywhere in the memory */
-#define IO_SPACE_LIMIT 0xffffffff
-
-/* io address mapping macro */
-#define __io(a)                __typesafe_io(a)
-
-#define __mem_pci(a)   (a)
-
-#endif /* __MACH_MXS_IO_H__ */
index 7aa5ac5d78bf13db1a7cab575708863e8820cd2b..80ac1fca8a004d91bf7f5be1fa4c7adfaf703841 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 
 #include <asm/proc-fns.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 #include <mach/mxs.h>
 #include <mach/common.h>
index 59e67979f197bb4908efc1e617911183cc6c5b3d..aa627465d914dcab43469311c48fdb61be800fdc 100644 (file)
@@ -168,7 +168,7 @@ void __init netx_init_irq(void)
 {
        int irq;
 
-       vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
+       vic_init(io_p2v(NETX_PA_VIC), 0, ~0, 0);
 
        for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
                irq_set_chip_and_handler(irq, &netx_hif_chip,
index 517a2bd378428740f8ac044d3b7c6c4d7ce36566..b661af2f214592c05fe61d7d999c978703c0461c 100644 (file)
@@ -33,7 +33,7 @@
 #define XMAC_MEM_SIZE 0x1000
 #define SRAM_MEM_SIZE 0x8000
 
-#define io_p2v(x) ((x) - NETX_IO_PHYS + NETX_IO_VIRT)
+#define io_p2v(x) IOMEM((x) - NETX_IO_PHYS + NETX_IO_VIRT)
 #define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS)
 
 #endif
diff --git a/arch/arm/mach-netx/include/mach/io.h b/arch/arm/mach-netx/include/mach/io.h
deleted file mode 100644 (file)
index c3921cb..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-netx/include/mach/io.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)            (a)
-
-#endif
index 5a03e7ccb01a65e64e9f9cf0e2c337a635100738..fdde22b58ac34bd9d2ae467c5851b7d50b4a187b 100644 (file)
  *********************************/
 
 /* Registers */
-#define NETX_SYSTEM_REG(ofs)            __io(NETX_VA_SYSTEM + (ofs))
+#define NETX_SYSTEM_REG(ofs)            IOMEM(NETX_VA_SYSTEM + (ofs))
 #define NETX_SYSTEM_BOO_SR          NETX_SYSTEM_REG(0x00)
 #define NETX_SYSTEM_IOC_CR          NETX_SYSTEM_REG(0x04)
 #define NETX_SYSTEM_IOC_MR          NETX_SYSTEM_REG(0x08)
  *******************************/
 
 /* Registers */
-#define NETX_GPIO_REG(ofs)                     __io(NETX_VA_GPIO + (ofs))
+#define NETX_GPIO_REG(ofs)                     IOMEM(NETX_VA_GPIO + (ofs))
 #define NETX_GPIO_CFG(gpio)                NETX_GPIO_REG(0x0  + ((gpio)<<2))
 #define NETX_GPIO_THRESHOLD_CAPTURE(gpio)  NETX_GPIO_REG(0x40 + ((gpio)<<2))
 #define NETX_GPIO_COUNTER_CTRL(counter)    NETX_GPIO_REG(0x80 + ((counter)<<2))
  *******************************/
 
 /* Registers */
-#define NETX_PIO_REG(ofs)        __io(NETX_VA_PIO + (ofs))
+#define NETX_PIO_REG(ofs)        IOMEM(NETX_VA_PIO + (ofs))
 #define NETX_PIO_INPIO       NETX_PIO_REG(0x0)
 #define NETX_PIO_OUTPIO      NETX_PIO_REG(0x4)
 #define NETX_PIO_OEPIO       NETX_PIO_REG(0x8)
  *******************************/
 
 /* Registers */
-#define NETX_MIIMU           __io(NETX_VA_MIIMU)
+#define NETX_MIIMU           IOMEM(NETX_VA_MIIMU)
 
 /* Bits */
 #define MIIMU_SNRDY        (1<<0)
  *******************************/
 
 /* Registers */
-#define NETX_PFIFO_REG(ofs)               __io(NETX_VA_PFIFO + (ofs))
+#define NETX_PFIFO_REG(ofs)               IOMEM(NETX_VA_PFIFO + (ofs))
 #define NETX_PFIFO_BASE(pfifo)        NETX_PFIFO_REG(0x00 + ((pfifo)<<2))
 #define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2))
 #define NETX_PFIFO_RESET              NETX_PFIFO_REG(0x100)
  *******************************/
 
 /* Registers */
-#define NETX_MEMCR_REG(ofs)               __io(NETX_VA_MEMCR + (ofs))
+#define NETX_MEMCR_REG(ofs)               IOMEM(NETX_VA_MEMCR + (ofs))
 #define NETX_MEMCR_SRAM_CTRL(cs)      NETX_MEMCR_REG(0x0 + 4 * (cs)) /* SRAM for CS 0..2 */
 #define NETX_MEMCR_SDRAM_CFG_CTRL     NETX_MEMCR_REG(0x40)
 #define NETX_MEMCR_SDRAM_TIMING_CTRL  NETX_MEMCR_REG(0x44)
  *******************************/
 
 /* Registers */
-#define NETX_DPMAS_REG(ofs)               __io(NETX_VA_DPMAS + (ofs))
+#define NETX_DPMAS_REG(ofs)               IOMEM(NETX_VA_DPMAS + (ofs))
 #define NETX_DPMAS_SYS_STAT           NETX_DPMAS_REG(0x4d8)
 #define NETX_DPMAS_INT_STAT           NETX_DPMAS_REG(0x4e0)
 #define NETX_DPMAS_INT_EN             NETX_DPMAS_REG(0x4f0)
 /*******************************
  * I2C                         *
  *******************************/
-#define NETX_I2C_REG(ofs)      __io(NETX_VA_I2C, (ofs))
+#define NETX_I2C_REG(ofs)      IOMEM(NETX_VA_I2C, (ofs))
 #define NETX_I2C_CTRL  NETX_I2C_REG(0x0)
 #define NETX_I2C_DATA  NETX_I2C_REG(0x4)
 
diff --git a/arch/arm/mach-nomadik/include/mach/io.h b/arch/arm/mach-nomadik/include/mach/io.h
deleted file mode 100644 (file)
index 2e1eca1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-nomadik/include/mach/io.h   (copied from mach-sa1100)
- *
- * Copyright (C) 1997-1999 Russell King
- *
- * Modifications:
- *  06-12-1997  RMK     Created.
- *  07-04-1999  RMK     Major cleanup
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)         __typesafe_io(a)
-#define __mem_pci(a)    (a)
-
-#endif
index 399c4c49722f91b093a05322bcd8bfb7dd64ed0b..a051cb8ae57fc2a67e943479150d7d11af260fc7 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #include <plat/board-ams-delta.h>
 
index f24c1e2c5044a37022ceee1f86ca774b6c257067..2b28e1da14b09fa6c4e4d089b4895c36dee1606f 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <asm/system_info.h>
 
 #include <plat/cpu.h>
 
index fa0f32a686aa73669c9de53945461647b57044e1..88f08cab17179d375f49169918305baffd6b32f0 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <mach/hardware.h>
-#include <mach/io.h>
 #include <mach/irqs.h>
 
 #include "../../iomap.h"
diff --git a/arch/arm/mach-omap1/include/mach/io.h b/arch/arm/mach-omap1/include/mach/io.h
deleted file mode 100644 (file)
index 37b12e1..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/io.h
- *
- * IO definitions for TI OMAP processors and boards
- *
- * Copied from arch/arm/mach-sa1100/include/mach/io.h
- * Copyright (C) 1997-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Modifications:
- *  06-12-1997 RMK     Created.
- *  07-04-1999 RMK     Major cleanup
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index d68175761c3d4fa399810ae51d04a86e90ba237f..330c4716b028e5eabc8b4fd8c025d40c60c0e876 100644 (file)
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifdef __ASSEMBLER__
-#define IOMEM(x)               (x)
-#else
-#define IOMEM(x)               ((void __force __iomem *)(x))
-#endif
-
 #define OMAP1_IO_OFFSET                0x01000000      /* Virtual IO = 0xfefb0000 */
 #define OMAP1_IO_ADDRESS(pa)   IOMEM((pa) - OMAP1_IO_OFFSET)
 
index 4b818eb9f911111bc18134a1617041c07ddf29bc..f6b14a14a95727c92dd697a7f7c63c9a8e4fda9a 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
index 9b99c28946239c89c473823295055857acc11909..3a066ee8d02c39201d0b20913944018cdf33ec83 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index da09f4364979808421b2f482b68a32ea84ec898c..936ed426b84f4d9f7841e217cf14b37114fbfcc5 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 5fdef7a34828adfc80fbe7463b95f290b916247d..087dba0df47e305fd059b97885c68f696d4c8ea5 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/io.h>
 #include <linux/spinlock.h>
 
-#include <asm/system.h>
 
 #include <plat/mux.h>
 
index 0779db150da7ccbaa90115ff41ea3a5f1179d8e6..0e628743bd03ca0f8fe202c8ef0693c48fbd9246 100644 (file)
@@ -36,8 +36,6 @@
 
 #include <asm/assembler.h>
 
-#include <mach/io.h>
-
 #include "iomap.h"
 #include "pm.h"
 
index 2ce0b9ab20e51ceb8af03e738d71cd0ecffb4141..00e9d9e9adf1107a442e7454e1f4434cdf54805d 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/assembler.h>
 
-#include <mach/io.h>
 #include <mach/hardware.h>
 
 #include "iomap.h"
index 2fae6a2740f18e0e1b2fa6c910adccd48dae3d7b..4d8dd9a1b04cedc07fb1a1e0689ae610e3188480 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/irq.h>
 #include <asm/sched_clock.h>
index a2e6d0709df25386b3c1f4cabb348ad9b08b3190..325b9a0aa4a00c9d71bdcf4d3f13dc7732ebe136 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
index 30768c2f53fd2bdb81d7c3f403c713fb501595ea..37dcb1bc025ea05674d3972d831455a462e43c7f 100644 (file)
@@ -490,21 +490,22 @@ static struct platform_device omap_vwlan_device = {
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
-       int ret = 0;
+       int irq = 0;
        struct platform_device *pdev = container_of(dev,
                                struct platform_device, dev);
        struct omap_mmc_platform_data *pdata = dev->platform_data;
 
        /* Setting MMC1 Card detect Irq */
        if (pdev->id == 0) {
-               ret = twl6030_mmc_card_detect_config();
-               if (ret)
+               irq = twl6030_mmc_card_detect_config();
+               if (irq < 0) {
                        pr_err("Failed configuring MMC1 card detect\n");
-               pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
-                                               MMCDETECT_INTR_OFFSET;
+                       return irq;
+               }
+               pdata->slots[0].card_detect_irq = irq;
                pdata->slots[0].card_detect = twl6030_mmc_card_detect;
        }
-       return ret;
+       return 0;
 }
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
index 8842e04aef013a9d6efce34a16f64c9c79b27321..ae2251fa4a69346567a816e01aa4c2b2601ed875 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
+#include <asm/system_info.h>
 
 #include <plat/board.h>
 #include "common.h"
index e9071a57c37b669ca69561a255773c401f487c5b..8bf8e99c358e494b235d3460954dad789e1b2754 100644 (file)
@@ -238,7 +238,7 @@ struct wl12xx_platform_data omap_panda_wlan_data  __initdata = {
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
-       int ret = 0;
+       int irq = 0;
        struct platform_device *pdev = container_of(dev,
                                struct platform_device, dev);
        struct omap_mmc_platform_data *pdata = dev->platform_data;
@@ -249,14 +249,15 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
        }
        /* Setting MMC1 Card detect Irq */
        if (pdev->id == 0) {
-               ret = twl6030_mmc_card_detect_config();
-                if (ret)
+               irq = twl6030_mmc_card_detect_config();
+               if (irq < 0) {
                        dev_err(dev, "%s: Error card detect config(%d)\n",
-                               __func__, ret);
-                else
-                       pdata->slots[0].card_detect = twl6030_mmc_card_detect;
+                               __func__, irq);
+                       return irq;
+               }
+               pdata->slots[0].card_detect = twl6030_mmc_card_detect;
        }
-       return ret;
+       return 0;
 }
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
index 16aebfb8a7ec7f5061fc0ba77a94469796f666b4..f120997309af261a0bb9c68e1d8eb57ae6e09bbf 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/mmc/host.h>
 #include <linux/power/isp1704_charger.h>
+#include <asm/system_info.h>
 
 #include <plat/mcspi.h>
 #include <plat/board.h>
index 981b9f9111a417e959aec8e111bce0e61238e9be..480fb8f09aeda407a1578e521483768e48c9784c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/list.h>
+#include <linux/io.h>
 
 #include <plat/hardware.h>
 #include <plat/clkdev_omap.h>
index 79b98f22f207825c896dddac914f8e7a0536dea1..c03c1108468e1a59f5f203de7d092928e06bae79 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/clk.h>
+#include <linux/io.h>
 
 #include <plat/hardware.h>
 #include <plat/clkdev_omap.h>
index 8121720e942ffdb10d14cd6fdde29aa691f7446e..100db6217f39984428ba49df988df65c2307f936 100644 (file)
@@ -316,6 +316,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
        mmc->slots[0].pm_caps = c->pm_caps;
        mmc->slots[0].internal_clock = !c->ext_clock;
        mmc->dma_mask = 0xffffffff;
+       mmc->max_freq = c->max_freq;
        if (cpu_is_omap44xx())
                mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
        else
index 07831cc3c171d39bcc96b1f3fa8e20615ac804ba..7f2e790e0929a9a23a13015c32cc119b81593c2d 100644 (file)
@@ -27,6 +27,8 @@ struct omap2_hsmmc_info {
        char    *name;          /* or NULL for default */
        struct platform_device *pdev;   /* mmc controller instance */
        int     ocr_mask;       /* temporary HACK */
+       int     max_freq;       /* maximum clock, if constrained by external
+                                * circuitry, or 0 for default */
        /* Remux (pad configuration) when powering on/off */
        void (*remux)(struct device *dev, int slot, int power_on);
        /* init some special card */
diff --git a/arch/arm/mach-omap2/include/mach/io.h b/arch/arm/mach-omap2/include/mach/io.h
deleted file mode 100644 (file)
index b8758c8..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/io.h
- *
- * IO definitions for TI OMAP processors and boards
- *
- * Copied from arch/arm/mach-sa1100/include/mach/io.h
- * Copyright (C) 1997-1999 Russell King
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Modifications:
- *  06-12-1997 RMK     Created.
- *  07-04-1999 RMK     Major cleanup
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index e6f958165296963af5776dd117b5ed22f1027a58..0812b154f5b5aa109ea3c5957e05b111be819793 100644 (file)
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifdef __ASSEMBLER__
-#define IOMEM(x)               (x)
-#else
-#define IOMEM(x)               ((void __force __iomem *)(x))
-#endif
-
 #define OMAP2_L3_IO_OFFSET     0x90000000
 #define OMAP2_L3_IO_ADDRESS(pa)        IOMEM((pa) + OMAP2_L3_IO_OFFSET) /* L3 */
 
index f26b2faa16947c042fe1563fed8b9d5b23b8488e..65c33911341fcf589b1e4372e9f5adbbada62d21 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 
 #include <plat/omap_hwmod.h>
 
index 63ab686834c12cf42520e13af6da51b659c305f8..13670aa84e58707ba0fdd284afbcee10a995b5e7 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/smp_scu.h>
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/suspend.h>
 #include <asm/hardware/cache-l2x0.h>
index 5ca45ca76946fa777a046e45443b74395d4e0238..95442b69ae27111fc4bf5dba66eaaa8e01c6547a 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <asm/mach-types.h>
+#include <asm/system_misc.h>
 
 #include <plat/clock.h>
 #include <plat/sram.h>
index 027a537d72b282f533a35e05bbc15b771dfb8ff8..238defc6f6df26a185794510f8f031d0848afda8 100644 (file)
@@ -31,6 +31,7 @@
 #include <trace/events/power.h>
 
 #include <asm/suspend.h>
+#include <asm/system_misc.h>
 
 #include <plat/sram.h>
 #include "clockdomain.h"
index 91e0b1c9b76c6c594f4e4d3a200d090f32f5401a..9ccaadc2cf071011c39713548bf557ced9b789f7 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <asm/system_misc.h>
 
 #include "common.h"
 #include "clockdomain.h"
index abd283400490396ea0c3e6f1da70dc1dda7425a3..9f6b83d1b193348a7af9e628cff41956c8684898 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/smp_scu.h>
 #include <asm/memory.h>
 #include <asm/hardware/cache-l2x0.h>
index 5dad38ec00ea1422c618d455e14cc3bd4c364d04..24481666d2cddb409cd0cd4e76113d06ee700f70 100644 (file)
@@ -21,6 +21,7 @@
 #include <net/dsa.h>
 #include <asm/page.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 #include <asm/timex.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index d2513ac79ff5c1b9c317e54b490bcc2744889530..2e6454c8d4baab451c251cfd69a8a40d225e7d56 100644 (file)
@@ -57,5 +57,14 @@ struct meminfo;
 struct tag;
 extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *);
 
+/*****************************************************************************
+ * Helpers to access Orion registers
+ ****************************************************************************/
+/*
+ * These are not preempt-safe.  Locks, if needed, must be taken
+ * care of by the caller.
+ */
+#define orion5x_setbits(r, mask)       writel(readl(r) | (mask), (r))
+#define orion5x_clrbits(r, mask)       writel(readl(r) & ~(mask), (r))
 
 #endif
index 91b0f47885977e80ba5109f6b4205ce4b30de3b8..c3ed15b8ea252484619a029d206f63d2170bffc5 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
+#include <asm/system_info.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h
deleted file mode 100644 (file)
index e9d9afd..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/io.h
- *
- * Tzachi Perelstein <tzachi@marvell.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include "orion5x.h"
-
-#define IO_SPACE_LIMIT         0xffffffff
-
-#define __io(a)                        __typesafe_io(a)
-#define __mem_pci(a)           (a)
-
-
-/*****************************************************************************
- * Helpers to access Orion registers
- ****************************************************************************/
-/*
- * These are not preempt-safe.  Locks, if needed, must be taken
- * care of by the caller.
- */
-#define orion5x_setbits(r, mask)       writel(readl(r) | (mask), (r))
-#define orion5x_clrbits(r, mask)       writel(readl(r) & ~(mask), (r))
-
-
-#endif
index 527213169db07348d57c27e336b984db53e5ec35..0c9e413b5805293756777bc1f0b8a3c04b2ec4c7 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/system.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index 9a8697b97dd7d75d023fafe413beb270d97f0dca..c1b5d8a580374d9e92443982eb83bfe34bf1788a 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/system.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index 09c73659f467021631a3f769a58d5c2c9401d9e9..949eaa8f12e3cd1a165ee5f696fdb5a545a31c0a 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/system.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index d6a91948e4dc58bea1124691eb336ddfd543e4ac..cb19e1661bb3dbabdde57626f0074d012e8440db 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
 #include <plat/addr-map.h>
+#include <mach/orion5x.h>
 #include "common.h"
 
 /*****************************************************************************
index c9abb8fbfa70462dfce29e7452cacd04a03073c1..7189827d641d09a0222ec90480c115227d123fc8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/timex.h>
 #include <linux/serial_reg.h>
+#include <mach/orion5x.h>
 #include "tsx09-common.h"
 #include "common.h"
 
diff --git a/arch/arm/mach-picoxcell/include/mach/io.h b/arch/arm/mach-picoxcell/include/mach/io.h
deleted file mode 100644 (file)
index 7573ec7..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No ioports, but needed for driver compatibility. */
-#define __io(a)                        __typesafe_io(a)
-/* No PCI possible on picoxcell. */
-#define __mem_pci(a)           (a)
-
-#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/irqs.h b/arch/arm/mach-picoxcell/include/mach/irqs.h
deleted file mode 100644 (file)
index 59eac1e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_IRQS_H
-#define __MACH_IRQS_H
-
-/* We dynamically allocate our irq_desc's. */
-#define NR_IRQS                                0
-
-#endif /* __MACH_IRQS_H */
index 4cfb40b2ec19f2b866da3e9e3b24b7a3451bcc66..be4c92858509f60975efadc3fd02c6d00084e996 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 7fa4bf2e21259884e41d0c610bc09b815bd51e06..a4739e9fb2fbca3e10f9fe59a5107f5d611b58c1 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/io.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
 #include <asm/dma-mapping.h>
diff --git a/arch/arm/mach-pnx4008/include/mach/io.h b/arch/arm/mach-pnx4008/include/mach/io.h
deleted file mode 100644 (file)
index cbf0904..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-/*
- *  arch/arm/mach-pnx4008/include/mach/io.h
- *
- * Author: Dmitry Chigirev <chigirev@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 7608c7a288cfbabf3f69ebc0ff7f43daaf41b017..41e4201972d5e409e9736b768e730de875476d5e 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
index 0c8aad4bb0dc877d0372f5ac7044597d41956f45..0cfe8af3d3be07b9bc29433e3f990b863487c973 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/mach/time.h>
diff --git a/arch/arm/mach-prima2/include/mach/io.h b/arch/arm/mach-prima2/include/mach/io.h
deleted file mode 100644 (file)
index 6c31e9e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-prima2/include/mach/io.h
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef __MACH_PRIMA2_IO_H
-#define __MACH_PRIMA2_IO_H
-
-#define IO_SPACE_LIMIT ((resource_size_t)0)
-
-#define __mem_pci(a)            (a)
-
-#endif
index b7a6091ce7914a819f1f902de3d32bce8391211d..0d024b1e916d417a67516101a54a409c36840d38 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <mach/map.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/time.h>
 
 #define SIRFSOC_TIMER_COUNTER_LO       0x0000
@@ -165,21 +166,9 @@ static struct irqaction sirfsoc_timer_irq = {
 };
 
 /* Overwrite weak default sched_clock with more precise one */
-unsigned long long notrace sched_clock(void)
+static u32 notrace sirfsoc_read_sched_clock(void)
 {
-       static int is_mapped;
-
-       /*
-        * sched_clock is called earlier than .init of sys_timer
-        * if we map timer memory in .init of sys_timer, system
-        * will panic due to illegal memory access
-        */
-       if (!is_mapped) {
-               sirfsoc_of_timer_map();
-               is_mapped = 1;
-       }
-
-       return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
+       return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
 }
 
 static void __init sirfsoc_clockevent_init(void)
@@ -210,6 +199,8 @@ static void __init sirfsoc_timer_init(void)
        BUG_ON(rate < CLOCK_TICK_RATE);
        BUG_ON(rate % CLOCK_TICK_RATE);
 
+       sirfsoc_of_timer_map();
+
        writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
        writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
        writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
@@ -217,6 +208,8 @@ static void __init sirfsoc_timer_init(void)
 
        BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
 
+       setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
+
        BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
 
        sirfsoc_clockevent_init();
index 61d3c72ded84d111e973d4a1dd4e3ab87f487b84..109ccd2a8885842dab6327e18ae4c4b49f0b35a0 100644 (file)
@@ -108,6 +108,7 @@ config CSB726_CSB701
 
 config MACH_ARMCORE
        bool "CompuLab CM-X255/CM-X270 modules"
+       select ARCH_HAS_DMA_SET_COHERENT_MASK if PCI
        select PXA27x
        select IWMMXT
        select PXA25x
index c91727d1fe097ab5bf01d0dbf261afefc7748775..9a8760b729132a5055880858d1aab1b0cdc90eda 100644 (file)
@@ -150,6 +150,7 @@ MACHINE_START(CAPC7117,
              "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
        .atag_offset = 0x100,
        .map_io = pxa3xx_map_io,
+       .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa3xx_init_irq,
        .handle_irq = pxa3xx_handle_irq,
        .timer = &pxa_timer,
index 1d5859d9a0e3299bfe55d82d21b9fe3ba123b94c..9ee2ad6a0a07ccdc20aa5d4878adfb4c635d9a2c 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/syscore_ops.h>
 
 #include <mach/pxa2xx-regs.h>
index 4b981b82d2a5401ecd50bc3b60df219df962433b..638eebedc883529a8be95937f542af38f919b4b7 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
+#include <asm/system_info.h>
 
 #include <mach/pxa300.h>
 #include <mach/pxa27x-udc.h>
@@ -853,6 +854,7 @@ static void __init cm_x300_fixup(struct tag *tags, char **cmdline,
 MACHINE_START(CM_X300, "CM-X300 module")
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 29d5d541f602f081b17b26acce6ef8f7bc148772..b2f227d361250e738c1f0b5a1d685b1ae9e44271 100644 (file)
@@ -310,6 +310,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa270_init,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -320,6 +321,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa270_income_init,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 0846d210cb05401be28b4b22840c683bcb09f6f8..bb6def8ec979d280ebf866c927612b5445424919 100644 (file)
@@ -186,6 +186,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa300_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 6ad3359063af4fe49727c0645367050b2a9adf36..d88e7b37f1dacfdc99a2991c5eab1d6d74d999bd 100644 (file)
@@ -256,6 +256,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa320_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 2b8ca0de8a3d7369b4c133ad6c29796f2ca85d7e..68cc75fac219ecaf7894a8812a93cebbec23b143 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/sizes.h>
+#include <asm/system_info.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <mach/pxa3xx-regs.h>
index 11f1e735966e534e3dd9dfe486e6581e32f2b55b..c1fe32db47552b7f0d73d5133675fab340791f18 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -730,6 +729,7 @@ static void __init fixup_corgi(struct tag *tags, char **cmdline,
 MACHINE_START(CORGI, "SHARP Corgi")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
@@ -742,6 +742,7 @@ MACHINE_END
 MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
@@ -754,6 +755,7 @@ MACHINE_END
 MACHINE_START(HUSKY, "SHARP Husky")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
index 39e265cfc86d1af6eefb5362a9a7cc2f5cedf189..048c4299473c586ab2a814b7bf625130c0b063ed 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/apm-emulation.h>
+#include <linux/io.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
index 88fbec05ec50f09e1724e431e761b1b9b4f1a261..b85b4ab7aac699e9254ad6828b6a1ed9d718fda7 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 
 #include <mach/pxa3xx-regs.h>
 
index fb5a51d834e5391c4cb407b4270009dcaf68b33c..67f0de37f46ebf1fb3308bd86d0d7ce6ed38fe71 100644 (file)
@@ -274,6 +274,7 @@ static void __init csb726_init(void)
 MACHINE_START(CSB726, "Cogent CSB726")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .init_machine   = csb726_init,
index 84f2d7015cfeced0850588ba7572968f1943f630..166eee5b8a70fe8f4bc555543ea8027564ee0392 100644 (file)
@@ -12,6 +12,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
+#include <mach/irqs.h>
 #include <mach/ohci.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/camera.h>
index d80c0ba9a0955613a2f393f5fefd1d882483ad52..c1b65da263358b6cf554728cb23b51e0631ec94c 100644 (file)
@@ -1301,6 +1301,7 @@ static void __init em_x270_init(void)
 MACHINE_START(EM_X270, "Compulab EM-X270")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -1311,6 +1312,7 @@ MACHINE_END
 MACHINE_START(EXEDA, "Compulab eXeda")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 5432ecb15defb2c0acd61068636aa78b24ccc949..42254175fcf46fd496dcad168fbd46cf1b8d9f1e 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 
 #include <mach/hardware.h>
-#include <asm/system.h>
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 
index ac3b1cef47519ed4c431cc2b576bfc76ebcda792..e529a35a44cee06a4a24fe39290a0fda172e505c 100644 (file)
@@ -235,6 +235,7 @@ static void __init gumstix_init(void)
 MACHINE_START(GUMSTIX, "Gumstix")
        .atag_offset    = 0x100, /* match u-boot bi_boot_params */
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index fde6b4c873c40fba6fe1c0aad5d85d1f03272c8f..e7dec589f0141704587051c16e3cdbb65388de5b 100644 (file)
@@ -205,6 +205,7 @@ static void __init h5000_init(void)
 MACHINE_START(H5400, "HP iPAQ H5000")
        .atag_offset = 0x100,
        .map_io = pxa25x_map_io,
+       .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
        .timer = &pxa_timer,
index 26d069a9f900117269936685f86a504fdb55f672..2962de898da9eefb0c1e35649e18468642b2abe4 100644 (file)
@@ -160,6 +160,7 @@ static void __init himalaya_init(void)
 MACHINE_START(HIMALAYA, "HTC Himalaya")
        .atag_offset = 0x100,
        .map_io = pxa25x_map_io,
+       .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
        .init_machine = himalaya_init,
index 67400192ed3b9d6532792e967a207f25a933c89a..1d02eabc9c654bb18751a9b802c2f3cdbc8c83a5 100644 (file)
@@ -193,6 +193,7 @@ static void __init icontrol_init(void)
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 8af1840e12cc4d8cdb6b24dd2f9e46110c59139d..6ff466bd43e8840b76bc71b6f1bcebc97d2092bb 100644 (file)
@@ -195,6 +195,7 @@ static void __init idp_map_io(void)
 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
        /* Maintainer: Vibren Technologies */
        .map_io         = idp_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index 8184669dde28116aad82b8854f2346bbac6d00be..56d92e5cad85f971eb813eced20f26ea0fe25688 100644 (file)
@@ -40,7 +40,6 @@
 #define io_p2v(x) IOMEM(0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 
 #ifndef __ASSEMBLY__
-# define IOMEM(x) ((void __iomem *)(x))
 # define __REG(x)      (*((volatile u32 __iomem *)io_p2v(x)))
 
 /* With indexed regs we don't want to feed the index through io_p2v()
@@ -52,7 +51,6 @@
 
 #else
 
-# define IOMEM(x)      x 
 # define __REG(x)      io_p2v(x)
 # define __PREG(x)     io_v2p(x)
 
@@ -337,8 +335,4 @@ extern unsigned int get_memclk_frequency_10khz(void);
 extern unsigned long get_clock_tick_rate(void);
 #endif
 
-#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
-#define ARCH_HAS_DMA_SET_COHERENT_MASK
-#endif
-
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h
deleted file mode 100644 (file)
index fdca3be..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-pxa/include/mach/io.h
- *
- * Copied from asm/arch/sa1100/io.h
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#include <mach/hardware.h>
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 32975adf3ca4927a2d77eba14efb1ad7bddd0638..8765782dd955f129a9e510f749de6fabee5a9e92 100644 (file)
  */
 #define IRQ_BOARD_START                (PXA_GPIO_IRQ_BASE + PXA_NR_BUILTIN_GPIO)
 
-#define NR_IRQS                        (IRQ_BOARD_START)
+#define PXA_NR_IRQS            (IRQ_BOARD_START)
 
 #ifndef __ASSEMBLY__
 struct irq_data;
index 4c2d11cd824dda4415d1ad74af1a368ffdd9b439..1bfc4e822a4152439a1cd0220ee614147472edc6 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef ASM_ARCH_MAINSTONE_H
 #define ASM_ARCH_MAINSTONE_H
 
+#include <mach/irqs.h>
+
 #define MST_ETH_PHYS           PXA_CS4_PHYS
 
 #define MST_FPGA_PHYS          PXA_CS2_PHYS
index 8b9c17142d5a8ed89657eb83794ce4fd52071a05..06b060025d11f3d63607434c40628ffc25ffa917 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include <mach/pxa25x.h>
 #include <mach/idp.h>
index e26d5efe196972c0c0ac299ca81e5e42bbddc459..0bd85c884a7c39dcfdfe2bbb39c551240e77bf8c 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <mach/pxa25x.h>
 #include <mach/lubbock.h>
 
index db4af5eee8b21649b2dc1ef661bfb970896812c7..4058ab340fe6adcd2d4c0a7c995cdfd85f468cfb 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include <mach/pxa27x.h>
 #include <mach/mainstone.h>
index 5e26f3e93fddf5f8e4a56adb3cc53806839b6e36..6f4785b347c25f44af25b49a6786f7ad1cec4e6e 100644 (file)
@@ -34,6 +34,7 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
index 29b62afc6f7ca3d219b4f4498c4b62b3a6fee223..b0a842887780f9acbe32e4223b4fe769f49b88f1 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/syscore_ops.h>
 
 #include <mach/pxa2xx-regs.h>
index e80a3db735c26e6e9c32ffd34ef435246b2949c8..061d57009cee98aec4335c745d3a7a51cfd975ea 100644 (file)
@@ -758,6 +758,7 @@ MACHINE_START(MIOA701, "MIO A701")
        .atag_offset    = 0x100,
        .restart_mode   = 's',
        .map_io         = &pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = &pxa27x_init_irq,
        .handle_irq     = &pxa27x_handle_irq,
        .init_machine   = mioa701_machine_init,
index 169bf8f97af00028a76d314b2bb8efa2d6b19e93..152efbf093f6b1f08eb2f18a2e2707688bb2a475 100644 (file)
@@ -95,6 +95,7 @@ MACHINE_START(NEC_MP900, "MobilePro900/C")
        .atag_offset    = 0x220100,
        .timer          = &pxa_timer,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = mp900c_init,
index 1fa80f4f80c8484595c4f4a5a17cdaf931a9cc33..31e0433d83ba2ffee4e1ddd24460f360ea940446 100644 (file)
@@ -344,6 +344,7 @@ static void __init palmld_init(void)
 MACHINE_START(PALMLD, "Palm LifeDrive")
        .atag_offset    = 0x100,
        .map_io         = palmld_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 5ba14316bd9c273b386e6267582dc93aa1131463..0f6bd4fcfa3b1f311cde34c6a540c852e24efc20 100644 (file)
@@ -205,6 +205,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = palmt5_reserve,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 29b51b40f09df49a60a2ab07d91122f0f840ed74..e2d97eed07a7603224945b547d32cb0c1cd8ef40 100644 (file)
@@ -539,6 +539,7 @@ static void __init palmtc_init(void)
 MACHINE_START(PALMTC, "Palm Tungsten|C")
        .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index 5ebf49acb8279d321a61596718980dc45dadfa11..c054827c567f81805771e7a9160748dcb8124b68 100644 (file)
@@ -358,6 +358,7 @@ static void __init palmte2_init(void)
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
        .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index ec8249156c0846b1d6129b6c55ab7a431d23d2a4..fbdebee39a53dbbe57b6cfa8f2324b785d4429f5 100644 (file)
@@ -448,6 +448,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -461,6 +462,7 @@ MACHINE_START(CENTRO, "Palm Centro 685")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 6170d76dfba8f395a41ff16c6c16ac28d1760970..9507605ed547a5366abf75cb704ee7c23a50ee62 100644 (file)
@@ -366,6 +366,7 @@ static void __init palmtx_init(void)
 MACHINE_START(PALMTX, "Palm T|X")
        .atag_offset    = 0x100,
        .map_io         = palmtx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index b2dff9d415ebf69eedba22393913e74075bb75ac..a97b59965bb917a542ed252446cefd7cf3e037c0 100644 (file)
@@ -401,6 +401,7 @@ static void __init palmz72_init(void)
 MACHINE_START(PALMZ72, "Palm Zire72")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 744baee12c0cc83a70ef418231fd584fe323563a..89d98c83218953426d8f2bba646f51d0b4fe4a92 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 868270421b8c1bdcaa5000b5cb012c32063999f3..f8ec85450c42c123b8931fbb1d20196f0c884b85 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
index 40bb16501d8601789875c03bbef88dd87519c925..17cbc0c7bdb8dd6572ff9da306c359cfca2b5e20 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/io.h>
 
 #include <mach/pxa300.h>
 
index 8d614ecd8e998d3d663187656dd108ca29405e62..6dc99d4f2dc630065398d20a08817df5773e6cc8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/io.h>
 
 #include <mach/pxa320.h>
 
index 1570d457fea3b87f52629ce2b1982c27229c3d40..dffb7e813d98743e3330db699770f5862eca6d49 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/smemc.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 #include "devices.h"
index 22818c7694a8fdb142b619f32c801e3cc9424386..7d691e51cb54048d679440b766dba67a7b3c9f4c 100644 (file)
@@ -1090,6 +1090,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
        .atag_offset    = 0x100,
        .init_machine   = raumfeld_controller_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
@@ -1102,6 +1103,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
        .atag_offset    = 0x100,
        .init_machine   = raumfeld_connector_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
@@ -1114,6 +1116,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
        .atag_offset    = 0x100,
        .init_machine   = raumfeld_speaker_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index c8497b00cdfe8bcb66f791c2907fbea345290571..b4528899ef0842fc8dba00fe1720b15164145bda 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <asm/proc-fns.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-ost.h>
 #include <mach/reset.h>
index 0fe354efb9317a8d183b76ef23a5e1a056982c58..86c95a5d8533a2e6db55116afa13d26925f2232d 100644 (file)
@@ -598,6 +598,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 30989baf7f2aa93a9cc0bd3e60c909a4b9f17e80..bdf4cb88ca0a60b10e368ffb1c1335b4b4a52277 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/leds.h>
 #include <linux/suspend.h>
 #include <linux/gpio.h>
+#include <linux/io.h>
 
 #include <asm/mach-types.h>
 #include <mach/pm.h>
index abf355d0c92f4fda72ea75cdfeb146cfa32d4c48..df2ab0fb2aced7c34736019f123c9e8cdfe38a2f 100644 (file)
@@ -984,6 +984,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
        .restart_mode   = 'g',
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
@@ -997,6 +998,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
        .restart_mode   = 'g',
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
@@ -1010,6 +1012,7 @@ MACHINE_START(AKITA, "SHARP Akita")
        .restart_mode   = 'g',
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
index b0656e158d90409f249cc4a6965483bb68e1dc52..adb601a3762fb6e2612339fb306b959cd27a722d 100644 (file)
@@ -1006,6 +1006,7 @@ static void __init stargate2_init(void)
 #ifdef CONFIG_MACH_INTELMOTE2
 MACHINE_START(INTELMOTE2, "IMOTE 2")
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 9fb38e80e076ca984056031cadae43ba306060c5..736bfdc50ee61dedf68da32b8475c9283a500af0 100644 (file)
@@ -491,6 +491,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index b503049d6d2657f6147b0bc82929426e2fe9f463..3d6c9bd90de6b183cd741e891c926a4bcb841c7e 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 #include <mach/regs-ost.h>
+#include <mach/irqs.h>
 
 /*
  * This is PXA's sched_clock implementation. This has a resolution
index 0f30af617d8f47924eb1591928aa9a87627f3405..2b6ac00b2cd98ce24e3e5e34bf56d36698d54c87 100644 (file)
@@ -558,6 +558,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        .atag_offset    = 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -569,6 +570,7 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
        .atag_offset    = 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 023d6ca789de4f0126939b247a6972f4f1cb5498..130379fb9d0fbbd405c0df4a36aee790ea1244ec 100644 (file)
@@ -57,6 +57,7 @@
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
+#include <asm/system_info.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -994,6 +995,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
        .atag_offset    = 0x100,
        .map_io         = viper_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = viper_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index 1f5cfa96f6d6a244da2d43f867d666b8b9232138..c57ab636ea9c85f5f459c48c422ca6fb680e35f4 100644 (file)
@@ -718,6 +718,7 @@ static void __init vpac270_init(void)
 MACHINE_START(VPAC270, "Voipac PXA270")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 4bbe9a36fe74df730ca419f4bfeeb6c3be6516dc..4275713ccd1045e4410c9efb0ac10323e0ed9f79 100644 (file)
@@ -182,6 +182,7 @@ MACHINE_START(XCEP, "Iskratel XCEP")
        .atag_offset    = 0x100,
        .init_machine   = xcep_init,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index b6476848b5618dfc72f68f3f76dfdd1bee2d3533..fa8619970841b8e12a7b1b8a14e1844952e660a7 100644 (file)
@@ -721,6 +721,7 @@ static void __init z2_init(void)
 MACHINE_START(ZIPIT2, "Zipit Z2")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index a4dd1c3470502dc364d0965179596bf6013faf0c..af3d4f7646d76bd13f2cca2b6ad1f7cc850d5b20 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/suspend.h>
+#include <asm/system_info.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
index acd329afc3ac71a84d0aeea506942373760283c4..45868bb43cbd2fbcbfcdfff638dc15f1cbd7d38b 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
index eb55f05bef3a1554b1a65485eed8fd3bb529853a..57d9efba29561479dc7ba521c25f4f5cdee2b621 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 
 extern volatile int pen_release;
index 8a638d15797fc2448b0e60f2af333045bdf2d3ec..281e71c9752561ef635ea22af1b1df70d82ccf0a 100644 (file)
@@ -37,6 +37,6 @@
 #else
 #define IO_ADDRESS(x)          (x)
 #endif
-#define __io_address(n)                __io(IO_ADDRESS(n))
+#define __io_address(n)                IOMEM(IO_ADDRESS(n))
 
 #endif
diff --git a/arch/arm/mach-realview/include/mach/io.h b/arch/arm/mach-realview/include/mach/io.h
deleted file mode 100644 (file)
index f05bcdf..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-realview/include/mach/io.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 050d63c74cc10eabf776429875a301c70f17fe81..257166b21f3d8216f07e1f61999a7eb1d1105812 100644 (file)
 
 #include <mach/memory.h>
 
-#ifndef __ASSEMBLY__
-#define IOMEM(x) ((void __iomem *)(unsigned long)(x))
-#else
-#define IOMEM(x) x
-#endif /* __ASSEMBLY__ */
-
 /*
  * What hardware must be present
  */
index 695f4ed2e11bab87d45ccd8ee2574a2ca8939dcd..707071a7ea4ea15c572c028388346bc9ac6758b2 100644 (file)
@@ -28,9 +28,4 @@
  */
 #define __io(a)                (PCIO_BASE + ((a) << 2))
 
-/*
- * 1:1 mapping for ioremapped regions.
- */
-#define __mem_pci(x)   (x)
-
 #endif
index 731552d68adfe76a5a8b2f2d1235c0a90c03c350..f3fa259ce01f1546ce40be1ea382a05af6e42fb2 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/page.h>
 #include <asm/domain.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
index 118749f37c4cddf2df549218a218bd5dd850ee16..5dd1db4e267724275d90913d74246d6da122d2bc 100644 (file)
@@ -208,9 +208,4 @@ DECLARE_IO(int,l,"")
 #define outsw(p,d,l)   __raw_writesw(__ioaddr(p),d,l)
 #define outsl(p,d,l)   __raw_writesl(__ioaddr(p),d,l)
 
-/*
- * 1:1 mapping for ioremapped regions.
- */
-#define __mem_pci(x)   (x)
-
 #endif
index 061b6bb1a557015d051b65388951da535f900665..a3c5cb086ee23a736843f6e50ca5d075986885f2 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <plat/cpu-freq.h>
 
index c6eac98710934b23bd7a91a29826f1a600de34d0..d4bc7f960bbbe2fa047696258979f2c69190b73a 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <plat/cpu-freq.h>
 
index 0e9a71c90ed7343f86ed077d820926b8f2b03741..7743fade50dfa59e1c3d669d5aa55478adb993e1 100644 (file)
@@ -43,6 +43,7 @@
 #include <mach/hardware.h>
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-s3c2443-clock.h>
 
index b7778a9dafaff8e05946119d8c9ffaf0b2ceec90..ab648ad8fa508651624054ca2d9693f9d34fb1e5 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-s3c2443-clock.h>
 
index d15852f642b7db8ca5fe5169a36a02fe29eb067a..6f74118f60c60f66ffbd46f6f0c72821ea2bbc4d 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
+#include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
index bee7dcd4df7c34ad8fb381173d1a7250a80b418a..b313380342a5790efbcb62104353e54f44672dbd 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/vic.h>
+#include <asm/system_misc.h>
 
 #include <mach/map.h>
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-s3c64xx/include/mach/io.h b/arch/arm/mach-s3c64xx/include/mach/io.h
deleted file mode 100644 (file)
index de5716d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s3c64xxinclude/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S3C64XX based
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
index b6a67728cc88f957a9ee7513596fd2e41cedf3be..0ace108c3e3d710264f4c88dfa5676702723fbfc 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/mfd/wm831x/gpio.h>
 #include <linux/mfd/wm8994/pdata.h>
 
+#include <linux/regulator/machine.h>
+
 #include <sound/wm5100.h>
 #include <sound/wm8996.h>
 #include <sound/wm8962.h>
@@ -153,6 +155,14 @@ static const struct i2c_board_info wm1259_devs[] = {
        },
 };
 
+static struct regulator_init_data wm8994_ldo1 = {
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data wm8994_ldo2 = {
+       .supply_regulator = "WALLVDD",
+};
+
 static struct wm8994_pdata wm8994_pdata = {
        .gpio_base = CODEC_GPIO_BASE,
        .gpio_defaults = {
@@ -160,8 +170,8 @@ static struct wm8994_pdata wm8994_pdata = {
        },
        .irq_base = CODEC_IRQ_BASE,
        .ldo = {
-               { .supply = "WALLVDD" },
-               { .supply = "WALLVDD" },
+                { .init_data = &wm8994_ldo1, },
+                { .init_data = &wm8994_ldo2, },
        },
 };
 
index 9143f8b19962c315b8d7e2ac6395fbe660bfb7e6..6e6a0a9d6778b0b1fe41a6857cef015ee55bc39d 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/proc-fns.h>
+#include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
diff --git a/arch/arm/mach-s5p64x0/include/mach/io.h b/arch/arm/mach-s5p64x0/include/mach/io.h
deleted file mode 100644 (file)
index a3e095c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/io.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S5P64X0 based
- *
- * 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.
-*/
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
index ff71e2d467c606375a23e63e38c61f088a8f68d3..621908658861596a43e4817f6978e352eab7604d 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/proc-fns.h>
+#include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
diff --git a/arch/arm/mach-s5pc100/include/mach/io.h b/arch/arm/mach-s5pc100/include/mach/io.h
deleted file mode 100644 (file)
index 819acf5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for S5PC100 systems
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/io.h b/arch/arm/mach-s5pv210/include/mach/io.h
deleted file mode 100644 (file)
index 5ab9d56..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/io.h
- *
- * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * Based on arch/arm/mach-s5p6442/include/mach/io.h
- *
- * Default IO routines for S5PV210
- *
- * 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.
-*/
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H __FILE__
-
-/* No current ISA/PCI bus support. */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif /* __ASM_ARM_ARCH_IO_H */
index 1d0f71b17a2670a9ac30aed6bcfc163bf810afc1..7c524b4e415d7ec7843dcbd7987c663d2f447bd9 100644 (file)
 #include <video/sa1100fb.h>
 
 #include <asm/div64.h>
-#include <asm/system.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-sa1100/include/mach/io.h b/arch/arm/mach-sa1100/include/mach/io.h
deleted file mode 100644 (file)
index dfc27ff..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-sa1100/include/mach/io.h
- *
- * Copyright (C) 1997-1999 Russell King
- *
- * Modifications:
- *  06-12-1997 RMK     Created.
- *  07-04-1999 RMK     Major cleanup
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/*
- * __io() is required to be an equivalent mapping to __mem_pci() for
- * SOC_COMMON to work.
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 64e9b4b11b5454b83f192b93ac0b8ff0b5782d66..3699176bca94fc141a34a3294bd10a7d7afc5ca9 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <mach/assabet.h>
 
 #include "leds.h"
index cf1e38458b81c939ae3cf518a5c01ae687b02d79..f99fac3eedb6b9f528906f981cc8d9a0b338dd96 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 259b48e0be895b5b3c6ffcf50178b56c02a0b57f..040540fb7d8aa1157a930a32d577303915357ded 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 2bce137462e46a5b5ffa7753256fc841ed484350..6a2352436e6268989700ab9d9b84761add3b9bc1 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 0505a1fdcdb2b98f203d0db244fcf57aac12e1da..a51830c60e5348e360ee7f33b3e1a98c3fdf60b6 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index bf85b8b259d5b08a1f2b8e61f9a8792a800298f3..2fa499ec6afebf52cad16e2641192029a1cf44ef 100644 (file)
@@ -30,7 +30,6 @@
 #include <mach/hardware.h>
 #include <asm/memory.h>
 #include <asm/suspend.h>
-#include <asm/system.h>
 #include <asm/mach/time.h>
 
 extern int sa1100_finish_suspend(unsigned long);
index 9ccbcecc430baa679a8fd800dfe409a5744f34e3..1a45fc01ff1d939979c65367dc7dee1f06607186 100644 (file)
@@ -15,6 +15,4 @@
 
 #define __io(a)                 ((void __iomem *)(0xe0000000 + (a)))
 
-#define __mem_pci(addr) (addr)
-
 #endif
index ccd49189bbd01a58156f922ea990b9dd377513ff..25609076921fc01970ba6319b414bec74168afac 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/io.h>
 
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
 #define LED_STATE_CLAIMED      2
index 060e5644c49c4711668835d451885f552a63a210..34560cab45d916729ccf03733ca88aaa8f7c9023 100644 (file)
@@ -100,6 +100,10 @@ config MACH_MARZEN
 
 comment "SH-Mobile System Configuration"
 
+config CPU_HAS_INTEVT
+        bool
+       default y
+
 menu "Memory configuration"
 
 config MEMORY_START
index f50d7c8b1221bc2f9b32b6b3a0414d43a485c2ce..cb224a344af0ccfa11a460297038a4a79ed151ce 100644 (file)
@@ -43,6 +43,7 @@
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -584,7 +585,7 @@ static void __init ag5evm_init(void)
 
 #ifdef CONFIG_CACHE_L2X0
        /* Shared attribute override enable, 64K*8way */
-       l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff);
+       l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff);
 #endif
        sh73a0_add_standard_devices();
        platform_add_devices(ag5evm_devices, ARRAY_SIZE(ag5evm_devices));
index 8b2124da245d46ad2aca08c63e7431ce97e962a2..81fd95f7f52ada6b440f26cbff003a25c92fbef9 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/mach/time.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <mach/r8a7740.h>
+#include <mach/irqs.h>
 #include <video/sh_mobile_lcdc.h>
 
 /*
@@ -370,7 +371,7 @@ static void __init bonito_init(void)
 
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 32K*8way */
-       l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
 #endif
 
        r8a7740_add_standard_devices();
index b627e89037f5e567d15101b1e3fe3051bbfa94c0..39b6cf85ced6cc2d98d3132c56629ff0a7398874 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/dma-mapping.h>
+#include <mach/irqs.h>
 #include <mach/sh7367.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 46d757d2759d0120c37db14f79ce1d55b5015b11..0e5a39c670bc259731790e7f275bcfeb47ead4c9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
 #include <linux/dma-mapping.h>
+#include <mach/irqs.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 61c067294660f41d36dad57557459f30471a1701..200dcd42a3a0f819bc4581b8f9b82e0da9a3f962 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
@@ -507,7 +508,7 @@ static void __init kota2_init(void)
 
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 64K*8way */
-       l2x0_init(__io(0xf0100000), 0x40460000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
 #endif
        sh73a0_add_standard_devices();
        platform_add_devices(kota2_devices, ARRAY_SIZE(kota2_devices));
index ca609502d6cdda92dda69a3cc421e58d25e9b4c7..a125d4e114ec53db0500632fa7d8addaa5d99bee 100644 (file)
@@ -54,6 +54,7 @@
 #include <sound/sh_fsi.h>
 
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/sh7372.h>
 
 #include <asm/mach/arch.h>
index cbd5e4cd06d2b241a5d24ee67d578943234d4cf5..ef0e13bf0b3a46911564e1ef7515740a77028574 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
index 1b2334277e85d5cbad17a126698fdbc39aaefd7b..21b09b6455e4b7788057df17d624f3778a7cad21 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/suspend.h>
 #include <linux/module.h>
 #include <linux/err.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 static void shmobile_enter_wfi(void)
diff --git a/arch/arm/mach-shmobile/include/mach/io.h b/arch/arm/mach-shmobile/include/mach/io.h
deleted file mode 100644 (file)
index 7339fe4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __ASM_MACH_IO_H
-#define __ASM_MACH_IO_H
-
-#define IO_SPACE_LIMIT         0xffffffff
-
-#define __io(a)                        ((void __iomem *)(a))
-#define __mem_pci(a)           (a)
-
-#endif /* __ASM_MACH_IO_H */
index dcb714f4d75ab15c2dca37bc0843ad1de73872d6..4e686cc201fc8bacab46ad6aed6c01aac653c42c 100644 (file)
@@ -1,15 +1,11 @@
 #ifndef __ASM_MACH_IRQS_H
 #define __ASM_MACH_IRQS_H
 
-#define NR_IRQS         1024
+#include <linux/sh_intc.h>
 
 /* GIC */
 #define gic_spi(nr)            ((nr) + 32)
 
-/* INTCA */
-#define evt2irq(evt)           (((evt) >> 5) - 16)
-#define irq2evt(irq)           (((irq) + 16) << 5)
-
 /* INTCS */
 #define INTCS_VECT_BASE                0x2200
 #define INTCS_VECT(n, vect)    INTC_VECT((n), INTCS_VECT_BASE + (vect))
index 3bbcb3fa077566113cc23c23ad5f9bd1837cf8ca..540eaff08f34b614d487f4605ab266b3fd06da73 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
+#include <asm/system_misc.h>
+
 static inline void arch_reset(char mode, const char *cmd)
 {
        soft_restart(0);
index 272c84c20c839d5415bc9953c7b234a4f053e676..09c42afcb22dae848551c1306b922866fc78a957 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 5d92fcde2bc3fc1495d1155ffe1b022510d2a2fb..550b23df4fd44d9b3cb4f7db19606153482b8c3e 100644 (file)
@@ -42,8 +42,8 @@ static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
 
 void __init r8a7779_init_irq(void)
 {
-       void __iomem *gic_dist_base = __io(0xf0001000);
-       void __iomem *gic_cpu_base = __io(0xf0000100);
+       void __iomem *gic_dist_base = IOMEM(0xf0001000);
+       void __iomem *gic_cpu_base = IOMEM(0xf0000100);
 
        /* use GIC to handle interrupts */
        gic_init(0, 29, gic_dist_base, gic_cpu_base);
index cfde9bfc36699dec881fa738f2d19aec58075955..5bf776495b7521f43a4cfb71c8021485cda891ff 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 89afcaba99a1a74e132dc1264d249e0099d21944..6447e0af52d412123b222ea94978cc84969c4778 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 2af4e6e9bc5b3a852070367d80ba9e3b3e27c370..b84a460a340577f005d552099b00f4902d6e4a82 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 9857595eaa7925186f73664277c0ddf9a57a481b..ee447404c857ed5794eaf5cbe1153a9e2e2d5505 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
@@ -420,8 +421,8 @@ static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id)
 
 void __init sh73a0_init_irq(void)
 {
-       void __iomem *gic_dist_base = __io(0xf0001000);
-       void __iomem *gic_cpu_base = __io(0xf0000100);
+       void __iomem *gic_dist_base = IOMEM(0xf0001000);
+       void __iomem *gic_cpu_base = IOMEM(0xf0000100);
        void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
        int k, n;
 
index c38ba7b43ef83e2962eaf61d3cec6d7afbed3b8a..a18a4ae16d2bf7ff9072cda4bb70eae8392cf9f1 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <mach/common.h>
 #include <mach/r8a7779.h>
index fcf8b1761aef723c6f3e5f3bd1f2b42cf436e04a..a3bdb12acde99771357de0fb95c1e207ece71e3f 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/irq.h>
 #include <linux/bitrev.h>
 #include <linux/console.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/suspend.h>
index 74e52341dd1bda1352e70de479c75fa53a99356b..14edb5cffa7f23023d8224d055af3e7974a6807d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/sh_timer.h>
 #include <mach/r8a7740.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
index 6820d785493db3a2c1516cb4f1fc01461dae6579..12c6f529ab891eac5b4482930e7156adfa842ce6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index a51e1a1e6996ddf7a3bd097a23fdbc3071261ae0..2e3074ab75b3189cc239a8c06bdb51a31fce1391 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 4e818b7de7815fb466f0b4c5451fad7225859628..2fe8f83ca12492363821fd6462073783b21e9e2d 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pm_domain.h>
 #include <linux/dma-mapping.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh7372.h>
 #include <mach/common.h>
 #include <asm/mach/map.h>
index 9f146095098b258766bebe319b47adc225ec00ce..d576a6abbade8338a33eb8e39d290e29d57e302d 100644 (file)
@@ -32,6 +32,7 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <asm/mach/map.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
index b6a0734a738e472c684b949ce9029a095c03eed2..5bebffc10455ec88132dab1742da1f86b610bda8 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 9bb7b8575a1fed4c366dbc58f3dbafd72007670d..b62e19d4c9afeb97d00339d36279217a607e4914 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/smp_twd.h>
 #include <asm/hardware/gic.h>
 
-#define AVECR 0xfe700040
+#define AVECR IOMEM(0xfe700040)
 
 static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
        .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
@@ -138,7 +138,7 @@ void __init r8a7779_smp_prepare_cpus(void)
        scu_enable(scu_base_addr());
 
        /* Map the reset vector (in headsmp.S) */
-       __raw_writel(__pa(shmobile_secondary_vector), __io(AVECR));
+       __raw_writel(__pa(shmobile_secondary_vector), AVECR);
 
        /* enable cache coherency on CPU0 */
        modify_scu_cpu_psr(0, 3 << (cpu * 8));
index c0a9093ba3a8675f861871078bc50730fc4dae58..14ad8b052f1a0944400d41ec559bc7188b8c5571 100644 (file)
 #include <asm/smp_twd.h>
 #include <asm/hardware/gic.h>
 
-#define WUPCR          0xe6151010
-#define SRESCR         0xe6151018
-#define PSTR           0xe6151040
-#define SBAR            0xe6180020
-#define APARMBAREA      0xe6f10020
+#define WUPCR          IOMEM(0xe6151010)
+#define SRESCR         IOMEM(0xe6151018)
+#define PSTR           IOMEM(0xe6151040)
+#define SBAR           IOMEM(0xe6180020)
+#define APARMBAREA     IOMEM(0xe6f10020)
 
 static void __iomem *scu_base_addr(void)
 {
@@ -78,10 +78,10 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
        /* enable cache coherency */
        modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
-       if (((__raw_readl(__io(PSTR)) >> (4 * cpu)) & 3) == 3)
-               __raw_writel(1 << cpu, __io(WUPCR));    /* wake up */
+       if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
+               __raw_writel(1 << cpu, WUPCR);  /* wake up */
        else
-               __raw_writel(1 << cpu, __io(SRESCR));   /* reset */
+               __raw_writel(1 << cpu, SRESCR); /* reset */
 
        return 0;
 }
@@ -93,8 +93,8 @@ void __init sh73a0_smp_prepare_cpus(void)
        scu_enable(scu_base_addr());
 
        /* Map the reset vector (in headsmp.S) */
-       __raw_writel(0, __io(APARMBAREA));      /* 4k */
-       __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
+       __raw_writel(0, APARMBAREA);      /* 4k */
+       __raw_writel(__pa(shmobile_secondary_vector), SBAR);
 
        /* enable cache coherency on CPU0 */
        modify_scu_cpu_psr(0, 3 << (cpu * 8));
index c1febe13f709e6a24b0bcbf4d709d80d2f189bb0..4d1b86a49923bf7f28f004ad4bb8c4a3f902095f 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/suspend.h>
 #include <linux/module.h>
 #include <linux/err.h>
-#include <asm/system.h>
 #include <asm/io.h>
+#include <asm/system_misc.h>
 
 static int shmobile_suspend_default_enter(suspend_state_t suspend_state)
 {
index f67860cd649f3df1ee009425d5938feaf9fa0784..6c4841f5522345cb9cdf5c1e5d83cd332adfc644 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <asm/mach-types.h>
 #include <plat/clock.h>
diff --git a/arch/arm/mach-spear3xx/include/mach/io.h b/arch/arm/mach-spear3xx/include/mach/io.h
deleted file mode 100644 (file)
index 30cff8a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/io.h
- *
- * IO definitions for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_IO_H
-#define __MACH_IO_H
-
-#include <plat/io.h>
-
-#endif /* __MACH_IO_H */
index 358f2800f17b9023ba1666d305a83b84406f50da..a86499a8a15f706f702671a93b3fb67f8a3bb25d 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <plat/clock.h>
 #include <mach/misc_regs.h>
diff --git a/arch/arm/mach-spear6xx/include/mach/io.h b/arch/arm/mach-spear6xx/include/mach/io.h
deleted file mode 100644 (file)
index fb7c106..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/io.h
- *
- * IO definitions for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar Kumar<rajeev-dlh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_IO_H
-#define __MACH_IO_H
-
-#include <plat/io.h>
-
-#endif /* __MACH_IO_H */
-
index bb5ce39b733b014d5725ae16bc1f5526ad873ac4..7a065f0cf6338dfa6566b23d7a48e318c843a1f9 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 
-#include <asm/system.h>
 
 #include <mach/clk.h>
 
index f3294040d357d5b5cd53fe7bd7c943a7061f26fb..d8dc9ddd6d188ac0efa2ab1a3594e6a02e442b82 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 
 static inline void cpu_enter_lowpower(void)
 {
index 90069abd37bd84844c5fc29ce2fca73e66d9ec8e..8ce0661b8a3d34bf4ad9a4004de0606a4e7de547 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/serial_reg.h>
 
-#include <mach/io.h>
 #include <mach/iomap.h>
 #include <mach/irammap.h>
 
index f15defffb5d252f519cb838afa8cbc628a097248..fe700f9ce7dc993e4ceabfd10e7f86e5b76bc0b9 100644 (file)
 
 #define IO_SPACE_LIMIT 0xffff
 
-/* On TEGRA, many peripherals are very closely packed in
- * two 256MB io windows (that actually only use about 64KB
- * at the start of each).
- *
- * We will just map the first 1MB of each window (to minimize
- * pt entries needed) and provide a macro to transform physical
- * io addresses to an appropriate void __iomem *.
- *
- */
-
-#ifdef __ASSEMBLY__
-#define IOMEM(x)       (x)
-#else
-#define IOMEM(x)       ((void __force __iomem *)(x))
-#endif
-
-#define IO_IRAM_PHYS   0x40000000
-#define IO_IRAM_VIRT   IOMEM(0xFE400000)
-#define IO_IRAM_SIZE   SZ_256K
-
-#define IO_CPU_PHYS     0x50040000
-#define IO_CPU_VIRT     IOMEM(0xFE000000)
-#define IO_CPU_SIZE    SZ_16K
-
-#define IO_PPSB_PHYS   0x60000000
-#define IO_PPSB_VIRT   IOMEM(0xFE200000)
-#define IO_PPSB_SIZE   SZ_1M
-
-#define IO_APB_PHYS    0x70000000
-#define IO_APB_VIRT    IOMEM(0xFE300000)
-#define IO_APB_SIZE    SZ_1M
-
-#define IO_TO_VIRT_BETWEEN(p, st, sz)  ((p) >= (st) && (p) < ((st) + (sz)))
-#define IO_TO_VIRT_XLATE(p, pst, vst)  (((p) - (pst) + (vst)))
-
-#define IO_TO_VIRT(n) ( \
-       IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ?           \
-               IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) :     \
-       IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ?             \
-               IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :       \
-       IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?             \
-               IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :       \
-       IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?           \
-               IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :     \
-       NULL)
-
 #ifndef __ASSEMBLER__
 
-#define IO_ADDRESS(n) (IO_TO_VIRT(n))
-
 #ifdef CONFIG_TEGRA_PCI
 extern void __iomem *tegra_pcie_io_base;
 
@@ -88,7 +40,6 @@ static inline void __iomem *__io(unsigned long addr)
 #endif
 
 #define __io(a)         __io(a)
-#define __mem_pci(a)    (a)
 
 #endif
 
index cff672a344f4e70a0057da3163f6cca7b35fc60f..7e76da73121cd418d2114ac6cfec494d8522239c 100644 (file)
 # define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
 #endif
 
+/* On TEGRA, many peripherals are very closely packed in
+ * two 256MB io windows (that actually only use about 64KB
+ * at the start of each).
+ *
+ * We will just map the first 1MB of each window (to minimize
+ * pt entries needed) and provide a macro to transform physical
+ * io addresses to an appropriate void __iomem *.
+ *
+ */
+
+#define IO_IRAM_PHYS   0x40000000
+#define IO_IRAM_VIRT   IOMEM(0xFE400000)
+#define IO_IRAM_SIZE   SZ_256K
+
+#define IO_CPU_PHYS     0x50040000
+#define IO_CPU_VIRT     IOMEM(0xFE000000)
+#define IO_CPU_SIZE    SZ_16K
+
+#define IO_PPSB_PHYS   0x60000000
+#define IO_PPSB_VIRT   IOMEM(0xFE200000)
+#define IO_PPSB_SIZE   SZ_1M
+
+#define IO_APB_PHYS    0x70000000
+#define IO_APB_VIRT    IOMEM(0xFE300000)
+#define IO_APB_SIZE    SZ_1M
+
+#define IO_TO_VIRT_BETWEEN(p, st, sz)  ((p) >= (st) && (p) < ((st) + (sz)))
+#define IO_TO_VIRT_XLATE(p, pst, vst)  (((p) - (pst) + (vst)))
+
+#define IO_TO_VIRT(n) ( \
+       IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ?           \
+               IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) :     \
+       IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ?             \
+               IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :       \
+       IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?             \
+               IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :       \
+       IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?           \
+               IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :     \
+       NULL)
+
+#define IO_ADDRESS(n) (IO_TO_VIRT(n))
+
 #endif
index d23ee2db28273afd250ecf6b6981a1562cdf5fab..58b4baf9c483d8a737fd73d418b14375c7a308e1 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <asm/page.h>
 #include <asm/mach/map.h>
+#include <mach/iomap.h>
 
 #include "board.h"
 
index 8f9fde161c341c63931cdb93031db4e383f3d41b..5b20197bae7ffbe334c2f7f1ca6bf3167006832c 100644 (file)
@@ -23,7 +23,9 @@
  */
 
 #include <linux/linkage.h>
-#include <mach/io.h>
+
+#include <asm/assembler.h>
+
 #include <mach/iomap.h>
 
 #include "flowctrl.h"
diff --git a/arch/arm/mach-u300/include/mach/io.h b/arch/arm/mach-u300/include/mach/io.h
deleted file mode 100644 (file)
index 5d6b4c1..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/include/mach/io.h
- *
- *
- * Copyright (C) 2006-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * Dummy IO map for being able to use writew()/readw(),
- * writel()/readw() and similar accessor functions.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-#ifndef __MACH_IO_H
-#define __MACH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 035fdc9dbdb03ebb50e88873a67232707d4fbc50..7b7cba960b690945fbd9830e893eb3c27ade58c8 100644 (file)
  * the defines are used for setting up the I/O memory mapping.
  */
 
-#ifdef __ASSEMBLER__
-#define IOMEM(a) (a)
-#else
-#define IOMEM(a) (void __iomem *) a
-#endif
-
 /* NAND Flash CS0 */
 #define U300_NAND_CS0_PHYS_BASE                0x80000000
 
index d93d6dbef25b8a0a9c8c8a1647cb0bc93517ba0f..f84698936d360d198aeba20313ddbce4b936ff67 100644 (file)
@@ -23,7 +23,7 @@
        (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + U8500_IO_VIRTUAL)
 
 /* typesafe io address */
-#define __io_address(n)                __io(IO_ADDRESS(n))
+#define __io_address(n)                IOMEM(IO_ADDRESS(n))
 /* Used by some plat-nomadik code */
 #define io_p2v(n)              __io_address(n)
 
diff --git a/arch/arm/mach-ux500/include/mach/io.h b/arch/arm/mach-ux500/include/mach/io.h
deleted file mode 100644 (file)
index 1cf3f44..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-u8500/include/mach/io.h
- *
- * Copyright (C) 1997-1999 Russell King
- *
- * Modifications:
- *  06-12-1997 RMK     Created.
- *  07-04-1999 RMK     Major cleanup
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index d2d4131435a680b61fcb6f84f6b092affe72f5cd..7d34c52798b5dd1e7162d13eb63866cff62e2079 100644 (file)
@@ -13,7 +13,7 @@
 
 #define MOP500_AB8500_IRQ_BASE         IRQ_BOARD_START
 #define MOP500_AB8500_IRQ_END          (MOP500_AB8500_IRQ_BASE \
-                                        + AB8500_NR_IRQS)
+                                        + AB8500_MAX_NR_IRQS)
 
 /* TC35892 */
 #define TC35892_NR_INTERNAL_IRQS       8
index 0968772aedbe1bfac8f9438c759dfb65bb0c29b0..6bbd74e950abd102c22624cd42678b3f598a3d6a 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/hardware/arm_timer.h>
diff --git a/arch/arm/mach-versatile/include/mach/io.h b/arch/arm/mach-versatile/include/mach/io.h
deleted file mode 100644 (file)
index f067c14..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  arch/arm/mach-versatile/include/mach/io.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
index 51733b022d0433b2f1704f720fd93ed3a6a9af03..a6e23f4645289675cf3be0501e90650772064b62 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 
 /*
index 3034a4dab4a1a3a927ace6f2364393c5fbbcfbe4..c504a72b94d6808af80f9de8c30bd1e96dad88c8 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
-#include <asm/system.h>
+#include <asm/cp15.h>
 
 extern volatile int pen_release;
 
diff --git a/arch/arm/mach-vexpress/include/mach/io.h b/arch/arm/mach-vexpress/include/mach/io.h
deleted file mode 100644 (file)
index 13522d8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-vexpress/include/mach/io.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define __io(a)                __typesafe_io(a)
-#define __mem_pci(a)   (a)
-
-#endif
diff --git a/arch/arm/mach-vt8500/include/mach/io.h b/arch/arm/mach-vt8500/include/mach/io.h
deleted file mode 100644 (file)
index 46181ee..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/io.h
- *
- *  Copyright (C) 2010 Alexey Charkov
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define __io(a)                __typesafe_io((a) + 0xf0000000)
-#define __mem_pci(a)   (a)
-
-#endif
index 9a06619929090c43dd4993bfeeb3878319ac901b..9e4dd8b63c4a2e9fed3296960db34209f745c2e1 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-serial.h>
diff --git a/arch/arm/mach-w90x900/include/mach/io.h b/arch/arm/mach-w90x900/include/mach/io.h
deleted file mode 100644 (file)
index d96ab99..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/io.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/io.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * 1:1 mapping for ioremapped regions.
- */
-
-#define __mem_pci(a)   (a)
-#define __io(a)                __typesafe_io(a)
-
-#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
deleted file mode 100644 (file)
index 39d9885..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* arch/arm/mach-zynq/include/mach/io.h
- *
- *  Copyright (C) 2011 Xilinx
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_IO_H__
-#define __MACH_IO_H__
-
-/* Allow IO space to be anywhere in the memory */
-
-#define IO_SPACE_LIMIT 0xffff
-
-/* IO address mapping macros, nothing special at this time but required */
-
-#ifdef __ASSEMBLER__
-#define IOMEM(x)               (x)
-#else
-#define IOMEM(x)               ((void __force __iomem *)(x))
-#endif
-
-#define __io(a)                        __typesafe_io(a)
-#define __mem_pci(a)           (a)
-
-#endif
index caf14dc059e5dcfd35289af5e2d3dc6f392a273b..9107231aacc5ab6c7eaa9fc83e9d05d626084afb 100644 (file)
@@ -22,7 +22,8 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
+#include <asm/cp15.h>
+#include <asm/system_info.h>
 #include <asm/unaligned.h>
 
 #include "fault.h"
index e0b0e7a4ec68a3c577959e9116b9c7fa5d0be09d..dd3d59122cc374c80ad487ad57bc3f5fbc580325 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <plat/cache-feroceon-l2.h>
 
 /*
index b1e192ba8c2450cb75a8118f86f8b650be284c82..a53fd2aaa2f4b59397bfa01847b22cd991bcdd8b 100644 (file)
 
 static void __iomem *l2x0_base;
 static DEFINE_RAW_SPINLOCK(l2x0_lock);
-static uint32_t l2x0_way_mask; /* Bitmask of active ways */
-static uint32_t l2x0_size;
+static u32 l2x0_way_mask;      /* Bitmask of active ways */
+static u32 l2x0_size;
 
 struct l2x0_regs l2x0_saved_regs;
 
 struct l2x0_of_data {
-       void (*setup)(const struct device_node *, __u32 *, __u32 *);
+       void (*setup)(const struct device_node *, u32 *, u32 *);
        void (*save)(void);
        void (*resume)(void);
 };
@@ -288,7 +288,7 @@ static void l2x0_disable(void)
        raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void l2x0_unlock(__u32 cache_id)
+static void l2x0_unlock(u32 cache_id)
 {
        int lockregs;
        int i;
@@ -307,11 +307,11 @@ static void l2x0_unlock(__u32 cache_id)
        }
 }
 
-void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
+void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 {
-       __u32 aux;
-       __u32 cache_id;
-       __u32 way_size = 0;
+       u32 aux;
+       u32 cache_id;
+       u32 way_size = 0;
        int ways;
        const char *type;
 
@@ -388,7 +388,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
 
 #ifdef CONFIG_OF
 static void __init l2x0_of_setup(const struct device_node *np,
-                                __u32 *aux_val, __u32 *aux_mask)
+                                u32 *aux_val, u32 *aux_mask)
 {
        u32 data[2] = { 0, 0 };
        u32 tag = 0;
@@ -422,7 +422,7 @@ static void __init l2x0_of_setup(const struct device_node *np,
 }
 
 static void __init pl310_of_setup(const struct device_node *np,
-                                 __u32 *aux_val, __u32 *aux_mask)
+                                 u32 *aux_val, u32 *aux_mask)
 {
        u32 data[3] = { 0, 0, 0 };
        u32 tag[3] = { 0, 0, 0 };
@@ -548,7 +548,7 @@ static const struct of_device_id l2x0_ids[] __initconst = {
        {}
 };
 
-int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
 {
        struct device_node *np;
        struct l2x0_of_data *data;
index 50868651890f04e2e23c0d023cb54b4e9ec22d8f..1fbca05fe906aa647ce5a3297dbe9c4681e6a7fc 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/hardware/cache-tauros2.h>
 
 
index 5a32020471e3bab2fc1e966a6e968c17a87f1d37..6c3edeb66e74059a7e1398b09c0d224a1e253240 100644 (file)
@@ -18,7 +18,7 @@
  */
 #include <linux/init.h>
 #include <linux/highmem.h>
-#include <asm/system.h>
+#include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
 
index ec8c3befb9c8d857f8db99c33ee6a9cecf75ff1a..1267e64133b9251feea121d1170ed095b7734944 100644 (file)
 
 #include "mm.h"
 
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  L_PTE_MT_MINICACHE)
 
@@ -78,10 +74,9 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
 
        raw_spin_lock(&minicache_lock);
 
-       set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
-       flush_tlb_kernel_page(0xffff8000);
+       set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
 
-       mc_copy_user_page((void *)0xffff8000, kto);
+       mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
 
        raw_spin_unlock(&minicache_lock);
 
index 8b03a5814d005e0591e79885f562c401c23a6379..b9bcc9d79176a43c464ef562b2118a119d14a825 100644 (file)
@@ -24,9 +24,6 @@
 #error FIX ME
 #endif
 
-#define from_address   (0xffff8000)
-#define to_address     (0xffffc000)
-
 static DEFINE_RAW_SPINLOCK(v6_lock);
 
 /*
@@ -90,14 +87,11 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
         */
        raw_spin_lock(&v6_lock);
 
-       set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0);
-       set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0);
-
-       kfrom = from_address + (offset << PAGE_SHIFT);
-       kto   = to_address + (offset << PAGE_SHIFT);
+       kfrom = COPYPAGE_V6_FROM + (offset << PAGE_SHIFT);
+       kto   = COPYPAGE_V6_TO + (offset << PAGE_SHIFT);
 
-       flush_tlb_kernel_page(kfrom);
-       flush_tlb_kernel_page(kto);
+       set_top_pte(kfrom, mk_pte(from, PAGE_KERNEL));
+       set_top_pte(kto, mk_pte(to, PAGE_KERNEL));
 
        copy_page((void *)kto, (void *)kfrom);
 
@@ -111,8 +105,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
  */
 static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vaddr)
 {
-       unsigned int offset = CACHE_COLOUR(vaddr);
-       unsigned long to = to_address + (offset << PAGE_SHIFT);
+       unsigned long to = COPYPAGE_V6_TO + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
 
        /* FIXME: not highmem safe */
        discard_old_kernel_data(page_address(page));
@@ -123,8 +116,7 @@ static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vad
         */
        raw_spin_lock(&v6_lock);
 
-       set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0);
-       flush_tlb_kernel_page(to);
+       set_top_pte(to, mk_pte(page, PAGE_KERNEL));
        clear_page((void *)to);
 
        raw_spin_unlock(&v6_lock);
index 439d106ae63804461d9b4f4149ad310a604e2379..0fb85025344d936734f0ff695ed21c2626414560 100644 (file)
 
 #include "mm.h"
 
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
-#define COPYPAGE_MINICACHE     0xffff8000
-
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  L_PTE_MT_MINICACHE)
 
@@ -100,8 +94,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
 
        raw_spin_lock(&minicache_lock);
 
-       set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
-       flush_tlb_kernel_page(COPYPAGE_MINICACHE);
+       set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
 
        mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
 
index 1aa664a1999fce45c2548726b50b6fa924608ec2..db23ae4aaaaba3384d000181e4dfb1c9ac476e60 100644 (file)
@@ -214,7 +214,8 @@ static int __init consistent_init(void)
 core_initcall(consistent_init);
 
 static void *
-__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
+__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
+       const void *caller)
 {
        struct arm_vmregion *c;
        size_t align;
@@ -241,7 +242,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
         * Allocate a virtual address in the consistent mapping region.
         */
        c = arm_vmregion_alloc(&consistent_head, align, size,
-                           gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+                           gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller);
        if (c) {
                pte_t *pte;
                int idx = CONSISTENT_PTE_INDEX(c->vm_start);
@@ -320,14 +321,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
 
 #else  /* !CONFIG_MMU */
 
-#define __dma_alloc_remap(page, size, gfp, prot)       page_address(page)
+#define __dma_alloc_remap(page, size, gfp, prot, c)    page_address(page)
 #define __dma_free_remap(addr, size)                   do { } while (0)
 
 #endif /* CONFIG_MMU */
 
 static void *
 __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
-           pgprot_t prot)
+           pgprot_t prot, const void *caller)
 {
        struct page *page;
        void *addr;
@@ -349,7 +350,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                return NULL;
 
        if (!arch_is_coherent())
-               addr = __dma_alloc_remap(page, size, gfp, prot);
+               addr = __dma_alloc_remap(page, size, gfp, prot, caller);
        else
                addr = page_address(page);
 
@@ -374,7 +375,8 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gf
                return memory;
 
        return __dma_alloc(dev, size, handle, gfp,
-                          pgprot_dmacoherent(pgprot_kernel));
+                          pgprot_dmacoherent(pgprot_kernel),
+                          __builtin_return_address(0));
 }
 EXPORT_SYMBOL(dma_alloc_coherent);
 
@@ -386,7 +388,8 @@ void *
 dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
        return __dma_alloc(dev, size, handle, gfp,
-                          pgprot_writecombine(pgprot_kernel));
+                          pgprot_writecombine(pgprot_kernel),
+                          __builtin_return_address(0));
 }
 EXPORT_SYMBOL(dma_alloc_writecombine);
 
@@ -723,6 +726,9 @@ EXPORT_SYMBOL(dma_set_mask);
 
 static int __init dma_debug_do_init(void)
 {
+#ifdef CONFIG_MMU
+       arm_vmregion_create_proc("dma-mappings", &consistent_head);
+#endif
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
        return 0;
 }
index bb7eac381a8e60f619591e7c80c4ad30cc972d62..9055b5a84ec5614914ab19dc5ed54004a821370f 100644 (file)
@@ -21,8 +21,9 @@
 #include <linux/perf_event.h>
 
 #include <asm/exception.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/system_misc.h>
+#include <asm/system_info.h>
 #include <asm/tlbflush.h>
 
 #include "fault.h"
@@ -164,7 +165,8 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
        struct siginfo si;
 
 #ifdef CONFIG_DEBUG_USER
-       if (user_debug & UDBG_SEGV) {
+       if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
+           ((user_debug & UDBG_BUS)  && (sig == SIGBUS))) {
                printk(KERN_DEBUG "%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n",
                       tsk->comm, sig, addr, fsr);
                show_pte(tsk->mm, addr);
index 1a8d4aa821bec152bc1b87736328f7b42b88d1f5..77458548e031fe73d75a5a79ea36f923c95cc88a 100644 (file)
 #include <asm/cachetype.h>
 #include <asm/highmem.h>
 #include <asm/smp_plat.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 
 #include "mm.h"
 
 #ifdef CONFIG_CPU_CACHE_VIPT
 
-#define ALIAS_FLUSH_START      0xffff4000
-
 static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 {
-       unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
+       unsigned long to = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
        const int zero = 0;
 
-       set_pte_ext(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL), 0);
-       flush_tlb_kernel_page(to);
+       set_top_pte(to, pfn_pte(pfn, PAGE_KERNEL));
 
        asm(    "mcrr   p15, 0, %1, %0, c14\n"
        "       mcr     p15, 0, %2, c7, c10, 4"
@@ -42,13 +38,12 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 
 static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len)
 {
-       unsigned long colour = CACHE_COLOUR(vaddr);
+       unsigned long va = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
        unsigned long offset = vaddr & (PAGE_SIZE - 1);
        unsigned long to;
 
-       set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0);
-       to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset;
-       flush_tlb_kernel_page(to);
+       set_top_pte(va, pfn_pte(pfn, PAGE_KERNEL));
+       to = va + offset;
        flush_icache_range(to, to + len);
 }
 
index 5a21505d75508fd80a495a9a31945c108a489b99..21b9e1bf9b7714106b13ea7a3f3606875fb25ae3 100644 (file)
@@ -69,15 +69,14 @@ void *kmap_atomic(struct page *page)
         * With debugging enabled, kunmap_atomic forces that entry to 0.
         * Make sure it was indeed properly unmapped.
         */
-       BUG_ON(!pte_none(*(TOP_PTE(vaddr))));
+       BUG_ON(!pte_none(get_top_pte(vaddr)));
 #endif
-       set_pte_ext(TOP_PTE(vaddr), mk_pte(page, kmap_prot), 0);
        /*
         * When debugging is off, kunmap_atomic leaves the previous mapping
-        * in place, so this TLB flush ensures the TLB is updated with the
-        * new mapping.
+        * in place, so the contained TLB flush ensures the TLB is updated
+        * with the new mapping.
         */
-       local_flush_tlb_kernel_page(vaddr);
+       set_top_pte(vaddr, mk_pte(page, kmap_prot));
 
        return (void *)vaddr;
 }
@@ -96,8 +95,7 @@ void __kunmap_atomic(void *kvaddr)
                        __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
 #ifdef CONFIG_DEBUG_HIGHMEM
                BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-               set_pte_ext(TOP_PTE(vaddr), __pte(0), 0);
-               local_flush_tlb_kernel_page(vaddr);
+               set_top_pte(vaddr, __pte(0));
 #else
                (void) idx;  /* to kill a warning */
 #endif
@@ -121,10 +119,9 @@ void *kmap_atomic_pfn(unsigned long pfn)
        idx = type + KM_TYPE_NR * smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
-       BUG_ON(!pte_none(*(TOP_PTE(vaddr))));
+       BUG_ON(!pte_none(get_top_pte(vaddr)));
 #endif
-       set_pte_ext(TOP_PTE(vaddr), pfn_pte(pfn, kmap_prot), 0);
-       local_flush_tlb_kernel_page(vaddr);
+       set_top_pte(vaddr, pfn_pte(pfn, kmap_prot));
 
        return (void *)vaddr;
 }
@@ -132,11 +129,9 @@ void *kmap_atomic_pfn(unsigned long pfn)
 struct page *kmap_atomic_to_page(const void *ptr)
 {
        unsigned long vaddr = (unsigned long)ptr;
-       pte_t *pte;
 
        if (vaddr < FIXADDR_START)
                return virt_to_page(ptr);
 
-       pte = TOP_PTE(vaddr);
-       return pte_page(*pte);
+       return pte_page(get_top_pte(vaddr));
 }
index feacf4c7671236faf8f343002f1a5a4f601c3d4b..ab88ed4f8e08f0232b88f0138991ab96f5fc5544 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
+#include <asm/system_info.h>
 
 pgd_t *idmap_pgd;
 
index 245a55a0a5bbcd0db13beda940b16533533d1b61..595079fa9d1d2eb342afae05f3b29a4395b87331 100644 (file)
@@ -658,7 +658,9 @@ void __init mem_init(void)
 #ifdef CONFIG_HIGHMEM
                        "    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #endif
+#ifdef CONFIG_MODULES
                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+#endif
                        "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
                        "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
                        "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
@@ -677,7 +679,9 @@ void __init mem_init(void)
                        MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) *
                                (PAGE_SIZE)),
 #endif
+#ifdef CONFIG_MODULES
                        MLM(MODULES_VADDR, MODULES_END),
+#endif
 
                        MLK_ROUNDUP(_text, _etext),
                        MLK_ROUNDUP(__init_begin, __init_end),
index 80632e8d7538f33d5a6539df5a72a90fff52e7ec..4f55f5062ab71432153fa3775303ccba85d83420 100644 (file)
 #include <linux/vmalloc.h>
 #include <linux/io.h>
 
+#include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
+#include <asm/system_info.h>
 
 #include <asm/mach/map.h>
 #include "mm.h"
@@ -306,11 +308,15 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
 }
 EXPORT_SYMBOL(__arm_ioremap_pfn);
 
+void __iomem * (*arch_ioremap_caller)(unsigned long, size_t,
+                                     unsigned int, void *) =
+       __arm_ioremap_caller;
+
 void __iomem *
 __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
 {
-       return __arm_ioremap_caller(phys_addr, size, mtype,
-                       __builtin_return_address(0));
+       return arch_ioremap_caller(phys_addr, size, mtype,
+               __builtin_return_address(0));
 }
 EXPORT_SYMBOL(__arm_ioremap);
 
@@ -369,4 +375,11 @@ void __iounmap(volatile void __iomem *io_addr)
 
        vunmap(addr);
 }
-EXPORT_SYMBOL(__iounmap);
+
+void (*arch_iounmap)(volatile void __iomem *) = __iounmap;
+
+void __arm_iounmap(volatile void __iomem *io_addr)
+{
+       arch_iounmap(io_addr);
+}
+EXPORT_SYMBOL(__arm_iounmap);
index 70f6d3ea48340fb7d8ac2aa6d8e9046a467117c8..27f4a619b35d1c0039d7883c7804994c0540cdc6 100644 (file)
@@ -3,7 +3,31 @@
 /* the upper-most page table pointer */
 extern pmd_t *top_pmd;
 
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently, while 0xffff4000
+ * is reserved for VIPT aliasing flushing by generic code.
+ *
+ * Note that we don't allow VIPT aliasing caches with SMP.
+ */
+#define COPYPAGE_MINICACHE     0xffff8000
+#define COPYPAGE_V6_FROM       0xffff8000
+#define COPYPAGE_V6_TO         0xffffc000
+/* PFN alias flushing, for VIPT caches */
+#define FLUSH_ALIAS_START      0xffff4000
+
+static inline void set_top_pte(unsigned long va, pte_t pte)
+{
+       pte_t *ptep = pte_offset_kernel(top_pmd, va);
+       set_pte_ext(ptep, pte, 0);
+       local_flush_tlb_kernel_page(va);
+}
+
+static inline pte_t get_top_pte(unsigned long va)
+{
+       pte_t *ptep = pte_offset_kernel(top_pmd, va);
+       return *ptep;
+}
 
 static inline pmd_t *pmd_off_k(unsigned long virt)
 {
index 94c5a0c94f5e2e9a19da0509b5717004188ee31a..b86f8933ff918908e107afe40553388e0e207988 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 
+#include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/sections.h>
 #include <asm/cachetype.h>
@@ -25,6 +26,7 @@
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
 #include <asm/highmem.h>
+#include <asm/system_info.h>
 #include <asm/traps.h>
 
 #include <asm/mach/arch.h>
@@ -997,11 +999,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
 {
        struct map_desc map;
        unsigned long addr;
+       void *vectors;
 
        /*
         * Allocate the vector page early.
         */
-       vectors_page = early_alloc(PAGE_SIZE);
+       vectors = early_alloc(PAGE_SIZE);
+
+       early_trap_init(vectors);
 
        for (addr = VMALLOC_START; addr; addr += PMD_SIZE)
                pmd_clear(pmd_off_k(addr));
@@ -1041,7 +1046,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
         * location (0xffff0000).  If we aren't using high-vectors, also
         * create a mapping at the low-vectors virtual address.
         */
-       map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
+       map.pfn = __phys_to_pfn(virt_to_phys(vectors));
        map.virtual = 0xffff0000;
        map.length = PAGE_SIZE;
        map.type = MT_HIGH_VECTORS;
index 4fc6794cca4bfd0d0364000119df7722c6c85c8b..6486d2f253cdd9dba5758d4402b11746dc0bda0a 100644 (file)
@@ -86,13 +86,17 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
 }
 EXPORT_SYMBOL(__arm_ioremap);
 
+void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, unsigned int, void *);
+
 void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size,
                                   unsigned int mtype, void *caller)
 {
        return __arm_ioremap(phys_addr, size, mtype);
 }
 
-void __iounmap(volatile void __iomem *addr)
+void (*arch_iounmap)(volatile void __iomem *);
+
+void __arm_iounmap(volatile void __iomem *addr)
 {
 }
-EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(__arm_iounmap);
index a3e78ccabd655ef871c74b66b6a277eee29290d6..0acb089d0f70db818ce487fa67b0fb90b1b0b69d 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/highmem.h>
 #include <linux/slab.h>
 
+#include <asm/cp15.h>
 #include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
index 272558a133a36ec685d63f5f7f40fd33e73a0caa..d217e9795d74b0878edb666d0a73ac72b1d586cc 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "proc-macros.S"
 
index 036fdbfdd62f6e91e0c329c7c12a9152dca21d7b..a631016e1f8f6927961b12fc8377d32d7ea1662a 100644 (file)
@@ -1,5 +1,8 @@
+#include <linux/fs.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 
 #include "vmregion.h"
@@ -36,7 +39,7 @@
 
 struct arm_vmregion *
 arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
-                  size_t size, gfp_t gfp)
+                  size_t size, gfp_t gfp, const void *caller)
 {
        unsigned long start = head->vm_start, addr = head->vm_end;
        unsigned long flags;
@@ -52,6 +55,8 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
        if (!new)
                goto out;
 
+       new->caller = caller;
+
        spin_lock_irqsave(&head->vm_lock, flags);
 
        addr = rounddown(addr - size, align);
@@ -129,3 +134,72 @@ void arm_vmregion_free(struct arm_vmregion_head *head, struct arm_vmregion *c)
 
        kfree(c);
 }
+
+#ifdef CONFIG_PROC_FS
+static int arm_vmregion_show(struct seq_file *m, void *p)
+{
+       struct arm_vmregion *c = list_entry(p, struct arm_vmregion, vm_list);
+
+       seq_printf(m, "0x%08lx-0x%08lx %7lu", c->vm_start, c->vm_end,
+               c->vm_end - c->vm_start);
+       if (c->caller)
+               seq_printf(m, " %pS", (void *)c->caller);
+       seq_putc(m, '\n');
+       return 0;
+}
+
+static void *arm_vmregion_start(struct seq_file *m, loff_t *pos)
+{
+       struct arm_vmregion_head *h = m->private;
+       spin_lock_irq(&h->vm_lock);
+       return seq_list_start(&h->vm_list, *pos);
+}
+
+static void *arm_vmregion_next(struct seq_file *m, void *p, loff_t *pos)
+{
+       struct arm_vmregion_head *h = m->private;
+       return seq_list_next(p, &h->vm_list, pos);
+}
+
+static void arm_vmregion_stop(struct seq_file *m, void *p)
+{
+       struct arm_vmregion_head *h = m->private;
+       spin_unlock_irq(&h->vm_lock);
+}
+
+static const struct seq_operations arm_vmregion_ops = {
+       .start  = arm_vmregion_start,
+       .stop   = arm_vmregion_stop,
+       .next   = arm_vmregion_next,
+       .show   = arm_vmregion_show,
+};
+
+static int arm_vmregion_open(struct inode *inode, struct file *file)
+{
+       struct arm_vmregion_head *h = PDE(inode)->data;
+       int ret = seq_open(file, &arm_vmregion_ops);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+               m->private = h;
+       }
+       return ret;
+}
+
+static const struct file_operations arm_vmregion_fops = {
+       .open   = arm_vmregion_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+int arm_vmregion_create_proc(const char *path, struct arm_vmregion_head *h)
+{
+       proc_create_data(path, S_IRUSR, NULL, &arm_vmregion_fops, h);
+       return 0;
+}
+#else
+int arm_vmregion_create_proc(const char *path, struct arm_vmregion_head *h)
+{
+       return 0;
+}
+#endif
index 15e9f044db9feab45a25d79eed9e1f0dce5a2a1a..162be662c0888c87b492bd2e13a8b51d1e2288e7 100644 (file)
@@ -19,11 +19,14 @@ struct arm_vmregion {
        unsigned long           vm_end;
        struct page             *vm_pages;
        int                     vm_active;
+       const void              *caller;
 };
 
-struct arm_vmregion *arm_vmregion_alloc(struct arm_vmregion_head *, size_t, size_t, gfp_t);
+struct arm_vmregion *arm_vmregion_alloc(struct arm_vmregion_head *, size_t, size_t, gfp_t, const void *);
 struct arm_vmregion *arm_vmregion_find(struct arm_vmregion_head *, unsigned long);
 struct arm_vmregion *arm_vmregion_find_remove(struct arm_vmregion_head *, unsigned long);
 void arm_vmregion_free(struct arm_vmregion_head *, struct arm_vmregion *);
 
+int arm_vmregion_create_proc(const char *, struct arm_vmregion_head *);
+
 #endif
diff --git a/arch/arm/net/Makefile b/arch/arm/net/Makefile
new file mode 100644 (file)
index 0000000..c2c1084
--- /dev/null
@@ -0,0 +1,3 @@
+# ARM-specific networking code
+
+obj-$(CONFIG_BPF_JIT) += bpf_jit_32.o
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
new file mode 100644 (file)
index 0000000..6213584
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * Just-In-Time compiler for BPF filters on 32bit ARM
+ *
+ * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/filter.h>
+#include <linux/moduleloader.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/hwcap.h>
+
+#include "bpf_jit_32.h"
+
+/*
+ * ABI:
+ *
+ * r0  scratch register
+ * r4  BPF register A
+ * r5  BPF register X
+ * r6  pointer to the skb
+ * r7  skb->data
+ * r8  skb_headlen(skb)
+ */
+
+#define r_scratch      ARM_R0
+/* r1-r3 are (also) used for the unaligned loads on the non-ARMv7 slowpath */
+#define r_off          ARM_R1
+#define r_A            ARM_R4
+#define r_X            ARM_R5
+#define r_skb          ARM_R6
+#define r_skb_data     ARM_R7
+#define r_skb_hl       ARM_R8
+
+#define SCRATCH_SP_OFFSET      0
+#define SCRATCH_OFF(k)         (SCRATCH_SP_OFFSET + (k))
+
+#define SEEN_MEM               ((1 << BPF_MEMWORDS) - 1)
+#define SEEN_MEM_WORD(k)       (1 << (k))
+#define SEEN_X                 (1 << BPF_MEMWORDS)
+#define SEEN_CALL              (1 << (BPF_MEMWORDS + 1))
+#define SEEN_SKB               (1 << (BPF_MEMWORDS + 2))
+#define SEEN_DATA              (1 << (BPF_MEMWORDS + 3))
+
+#define FLAG_NEED_X_RESET      (1 << 0)
+
+struct jit_ctx {
+       const struct sk_filter *skf;
+       unsigned idx;
+       unsigned prologue_bytes;
+       int ret0_fp_idx;
+       u32 seen;
+       u32 flags;
+       u32 *offsets;
+       u32 *target;
+#if __LINUX_ARM_ARCH__ < 7
+       u16 epilogue_bytes;
+       u16 imm_count;
+       u32 *imms;
+#endif
+};
+
+int bpf_jit_enable __read_mostly;
+
+static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset)
+{
+       u8 ret;
+       int err;
+
+       err = skb_copy_bits(skb, offset, &ret, 1);
+
+       return (u64)err << 32 | ret;
+}
+
+static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset)
+{
+       u16 ret;
+       int err;
+
+       err = skb_copy_bits(skb, offset, &ret, 2);
+
+       return (u64)err << 32 | ntohs(ret);
+}
+
+static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset)
+{
+       u32 ret;
+       int err;
+
+       err = skb_copy_bits(skb, offset, &ret, 4);
+
+       return (u64)err << 32 | ntohl(ret);
+}
+
+/*
+ * Wrapper that handles both OABI and EABI and assures Thumb2 interworking
+ * (where the assembly routines like __aeabi_uidiv could cause problems).
+ */
+static u32 jit_udiv(u32 dividend, u32 divisor)
+{
+       return dividend / divisor;
+}
+
+static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
+{
+       if (ctx->target != NULL)
+               ctx->target[ctx->idx] = inst | (cond << 28);
+
+       ctx->idx++;
+}
+
+/*
+ * Emit an instruction that will be executed unconditionally.
+ */
+static inline void emit(u32 inst, struct jit_ctx *ctx)
+{
+       _emit(ARM_COND_AL, inst, ctx);
+}
+
+static u16 saved_regs(struct jit_ctx *ctx)
+{
+       u16 ret = 0;
+
+       if ((ctx->skf->len > 1) ||
+           (ctx->skf->insns[0].code == BPF_S_RET_A))
+               ret |= 1 << r_A;
+
+#ifdef CONFIG_FRAME_POINTER
+       ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC);
+#else
+       if (ctx->seen & SEEN_CALL)
+               ret |= 1 << ARM_LR;
+#endif
+       if (ctx->seen & (SEEN_DATA | SEEN_SKB))
+               ret |= 1 << r_skb;
+       if (ctx->seen & SEEN_DATA)
+               ret |= (1 << r_skb_data) | (1 << r_skb_hl);
+       if (ctx->seen & SEEN_X)
+               ret |= 1 << r_X;
+
+       return ret;
+}
+
+static inline int mem_words_used(struct jit_ctx *ctx)
+{
+       /* yes, we do waste some stack space IF there are "holes" in the set" */
+       return fls(ctx->seen & SEEN_MEM);
+}
+
+static inline bool is_load_to_a(u16 inst)
+{
+       switch (inst) {
+       case BPF_S_LD_W_LEN:
+       case BPF_S_LD_W_ABS:
+       case BPF_S_LD_H_ABS:
+       case BPF_S_LD_B_ABS:
+       case BPF_S_ANC_CPU:
+       case BPF_S_ANC_IFINDEX:
+       case BPF_S_ANC_MARK:
+       case BPF_S_ANC_PROTOCOL:
+       case BPF_S_ANC_RXHASH:
+       case BPF_S_ANC_QUEUE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static void build_prologue(struct jit_ctx *ctx)
+{
+       u16 reg_set = saved_regs(ctx);
+       u16 first_inst = ctx->skf->insns[0].code;
+       u16 off;
+
+#ifdef CONFIG_FRAME_POINTER
+       emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
+       emit(ARM_PUSH(reg_set), ctx);
+       emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
+#else
+       if (reg_set)
+               emit(ARM_PUSH(reg_set), ctx);
+#endif
+
+       if (ctx->seen & (SEEN_DATA | SEEN_SKB))
+               emit(ARM_MOV_R(r_skb, ARM_R0), ctx);
+
+       if (ctx->seen & SEEN_DATA) {
+               off = offsetof(struct sk_buff, data);
+               emit(ARM_LDR_I(r_skb_data, r_skb, off), ctx);
+               /* headlen = len - data_len */
+               off = offsetof(struct sk_buff, len);
+               emit(ARM_LDR_I(r_skb_hl, r_skb, off), ctx);
+               off = offsetof(struct sk_buff, data_len);
+               emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
+               emit(ARM_SUB_R(r_skb_hl, r_skb_hl, r_scratch), ctx);
+       }
+
+       if (ctx->flags & FLAG_NEED_X_RESET)
+               emit(ARM_MOV_I(r_X, 0), ctx);
+
+       /* do not leak kernel data to userspace */
+       if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst)))
+               emit(ARM_MOV_I(r_A, 0), ctx);
+
+       /* stack space for the BPF_MEM words */
+       if (ctx->seen & SEEN_MEM)
+               emit(ARM_SUB_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
+}
+
+static void build_epilogue(struct jit_ctx *ctx)
+{
+       u16 reg_set = saved_regs(ctx);
+
+       if (ctx->seen & SEEN_MEM)
+               emit(ARM_ADD_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
+
+       reg_set &= ~(1 << ARM_LR);
+
+#ifdef CONFIG_FRAME_POINTER
+       /* the first instruction of the prologue was: mov ip, sp */
+       reg_set &= ~(1 << ARM_IP);
+       reg_set |= (1 << ARM_SP);
+       emit(ARM_LDM(ARM_SP, reg_set), ctx);
+#else
+       if (reg_set) {
+               if (ctx->seen & SEEN_CALL)
+                       reg_set |= 1 << ARM_PC;
+               emit(ARM_POP(reg_set), ctx);
+       }
+
+       if (!(ctx->seen & SEEN_CALL))
+               emit(ARM_BX(ARM_LR), ctx);
+#endif
+}
+
+static int16_t imm8m(u32 x)
+{
+       u32 rot;
+
+       for (rot = 0; rot < 16; rot++)
+               if ((x & ~ror32(0xff, 2 * rot)) == 0)
+                       return rol32(x, 2 * rot) | (rot << 8);
+
+       return -1;
+}
+
+#if __LINUX_ARM_ARCH__ < 7
+
+static u16 imm_offset(u32 k, struct jit_ctx *ctx)
+{
+       unsigned i = 0, offset;
+       u16 imm;
+
+       /* on the "fake" run we just count them (duplicates included) */
+       if (ctx->target == NULL) {
+               ctx->imm_count++;
+               return 0;
+       }
+
+       while ((i < ctx->imm_count) && ctx->imms[i]) {
+               if (ctx->imms[i] == k)
+                       break;
+               i++;
+       }
+
+       if (ctx->imms[i] == 0)
+               ctx->imms[i] = k;
+
+       /* constants go just after the epilogue */
+       offset =  ctx->offsets[ctx->skf->len];
+       offset += ctx->prologue_bytes;
+       offset += ctx->epilogue_bytes;
+       offset += i * 4;
+
+       ctx->target[offset / 4] = k;
+
+       /* PC in ARM mode == address of the instruction + 8 */
+       imm = offset - (8 + ctx->idx * 4);
+
+       return imm;
+}
+
+#endif /* __LINUX_ARM_ARCH__ */
+
+/*
+ * Move an immediate that's not an imm8m to a core register.
+ */
+static inline void emit_mov_i_no8m(int rd, u32 val, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 7
+       emit(ARM_LDR_I(rd, ARM_PC, imm_offset(val, ctx)), ctx);
+#else
+       emit(ARM_MOVW(rd, val & 0xffff), ctx);
+       if (val > 0xffff)
+               emit(ARM_MOVT(rd, val >> 16), ctx);
+#endif
+}
+
+static inline void emit_mov_i(int rd, u32 val, struct jit_ctx *ctx)
+{
+       int imm12 = imm8m(val);
+
+       if (imm12 >= 0)
+               emit(ARM_MOV_I(rd, imm12), ctx);
+       else
+               emit_mov_i_no8m(rd, val, ctx);
+}
+
+#if __LINUX_ARM_ARCH__ < 6
+
+static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDRB_I(ARM_R3, r_addr, 1), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 3), ctx);
+       _emit(cond, ARM_LSL_I(ARM_R3, ARM_R3, 16), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R0, r_addr, 2), ctx);
+       _emit(cond, ARM_ORR_S(ARM_R3, ARM_R3, ARM_R1, SRTYPE_LSL, 24), ctx);
+       _emit(cond, ARM_ORR_R(ARM_R3, ARM_R3, ARM_R2), ctx);
+       _emit(cond, ARM_ORR_S(r_res, ARM_R3, ARM_R0, SRTYPE_LSL, 8), ctx);
+}
+
+static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 1), ctx);
+       _emit(cond, ARM_ORR_S(r_res, ARM_R2, ARM_R1, SRTYPE_LSL, 8), ctx);
+}
+
+static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx)
+{
+       emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx);
+       emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx);
+       emit(ARM_LSL_I(r_dst, r_dst, 8), ctx);
+       emit(ARM_LSL_R(r_dst, r_dst, 8), ctx);
+}
+
+#else  /* ARMv6+ */
+
+static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDR_I(r_res, r_addr, 0), ctx);
+#ifdef __LITTLE_ENDIAN
+       _emit(cond, ARM_REV(r_res, r_res), ctx);
+#endif
+}
+
+static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDRH_I(r_res, r_addr, 0), ctx);
+#ifdef __LITTLE_ENDIAN
+       _emit(cond, ARM_REV16(r_res, r_res), ctx);
+#endif
+}
+
+static inline void emit_swap16(u8 r_dst __maybe_unused,
+                              u8 r_src __maybe_unused,
+                              struct jit_ctx *ctx __maybe_unused)
+{
+#ifdef __LITTLE_ENDIAN
+       emit(ARM_REV16(r_dst, r_src), ctx);
+#endif
+}
+
+#endif /* __LINUX_ARM_ARCH__ < 6 */
+
+
+/* Compute the immediate value for a PC-relative branch. */
+static inline u32 b_imm(unsigned tgt, struct jit_ctx *ctx)
+{
+       u32 imm;
+
+       if (ctx->target == NULL)
+               return 0;
+       /*
+        * BPF allows only forward jumps and the offset of the target is
+        * still the one computed during the first pass.
+        */
+       imm  = ctx->offsets[tgt] + ctx->prologue_bytes - (ctx->idx * 4 + 8);
+
+       return imm >> 2;
+}
+
+#define OP_IMM3(op, r1, r2, imm_val, ctx)                              \
+       do {                                                            \
+               imm12 = imm8m(imm_val);                                 \
+               if (imm12 < 0) {                                        \
+                       emit_mov_i_no8m(r_scratch, imm_val, ctx);       \
+                       emit(op ## _R((r1), (r2), r_scratch), ctx);     \
+               } else {                                                \
+                       emit(op ## _I((r1), (r2), imm12), ctx);         \
+               }                                                       \
+       } while (0)
+
+static inline void emit_err_ret(u8 cond, struct jit_ctx *ctx)
+{
+       if (ctx->ret0_fp_idx >= 0) {
+               _emit(cond, ARM_B(b_imm(ctx->ret0_fp_idx, ctx)), ctx);
+               /* NOP to keep the size constant between passes */
+               emit(ARM_MOV_R(ARM_R0, ARM_R0), ctx);
+       } else {
+               _emit(cond, ARM_MOV_I(ARM_R0, 0), ctx);
+               _emit(cond, ARM_B(b_imm(ctx->skf->len, ctx)), ctx);
+       }
+}
+
+static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 5
+       emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
+
+       if (elf_hwcap & HWCAP_THUMB)
+               emit(ARM_BX(tgt_reg), ctx);
+       else
+               emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
+#else
+       emit(ARM_BLX_R(tgt_reg), ctx);
+#endif
+}
+
+static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ == 7
+       if (elf_hwcap & HWCAP_IDIVA) {
+               emit(ARM_UDIV(rd, rm, rn), ctx);
+               return;
+       }
+#endif
+       if (rm != ARM_R0)
+               emit(ARM_MOV_R(ARM_R0, rm), ctx);
+       if (rn != ARM_R1)
+               emit(ARM_MOV_R(ARM_R1, rn), ctx);
+
+       ctx->seen |= SEEN_CALL;
+       emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
+       emit_blx_r(ARM_R3, ctx);
+
+       if (rd != ARM_R0)
+               emit(ARM_MOV_R(rd, ARM_R0), ctx);
+}
+
+static inline void update_on_xread(struct jit_ctx *ctx)
+{
+       if (!(ctx->seen & SEEN_X))
+               ctx->flags |= FLAG_NEED_X_RESET;
+
+       ctx->seen |= SEEN_X;
+}
+
+static int build_body(struct jit_ctx *ctx)
+{
+       void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
+       const struct sk_filter *prog = ctx->skf;
+       const struct sock_filter *inst;
+       unsigned i, load_order, off, condt;
+       int imm12;
+       u32 k;
+
+       for (i = 0; i < prog->len; i++) {
+               inst = &(prog->insns[i]);
+               /* K as an immediate value operand */
+               k = inst->k;
+
+               /* compute offsets only in the fake pass */
+               if (ctx->target == NULL)
+                       ctx->offsets[i] = ctx->idx * 4;
+
+               switch (inst->code) {
+               case BPF_S_LD_IMM:
+                       emit_mov_i(r_A, k, ctx);
+                       break;
+               case BPF_S_LD_W_LEN:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+                       emit(ARM_LDR_I(r_A, r_skb,
+                                      offsetof(struct sk_buff, len)), ctx);
+                       break;
+               case BPF_S_LD_MEM:
+                       /* A = scratch[k] */
+                       ctx->seen |= SEEN_MEM_WORD(k);
+                       emit(ARM_LDR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_LD_W_ABS:
+                       load_order = 2;
+                       goto load;
+               case BPF_S_LD_H_ABS:
+                       load_order = 1;
+                       goto load;
+               case BPF_S_LD_B_ABS:
+                       load_order = 0;
+load:
+                       /* the interpreter will deal with the negative K */
+                       if ((int)k < 0)
+                               return -ENOTSUPP;
+                       emit_mov_i(r_off, k, ctx);
+load_common:
+                       ctx->seen |= SEEN_DATA | SEEN_CALL;
+
+                       if (load_order > 0) {
+                               emit(ARM_SUB_I(r_scratch, r_skb_hl,
+                                              1 << load_order), ctx);
+                               emit(ARM_CMP_R(r_scratch, r_off), ctx);
+                               condt = ARM_COND_HS;
+                       } else {
+                               emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
+                               condt = ARM_COND_HI;
+                       }
+
+                       _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data),
+                             ctx);
+
+                       if (load_order == 0)
+                               _emit(condt, ARM_LDRB_I(r_A, r_scratch, 0),
+                                     ctx);
+                       else if (load_order == 1)
+                               emit_load_be16(condt, r_A, r_scratch, ctx);
+                       else if (load_order == 2)
+                               emit_load_be32(condt, r_A, r_scratch, ctx);
+
+                       _emit(condt, ARM_B(b_imm(i + 1, ctx)), ctx);
+
+                       /* the slowpath */
+                       emit_mov_i(ARM_R3, (u32)load_func[load_order], ctx);
+                       emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
+                       /* the offset is already in R1 */
+                       emit_blx_r(ARM_R3, ctx);
+                       /* check the result of skb_copy_bits */
+                       emit(ARM_CMP_I(ARM_R1, 0), ctx);
+                       emit_err_ret(ARM_COND_NE, ctx);
+                       emit(ARM_MOV_R(r_A, ARM_R0), ctx);
+                       break;
+               case BPF_S_LD_W_IND:
+                       load_order = 2;
+                       goto load_ind;
+               case BPF_S_LD_H_IND:
+                       load_order = 1;
+                       goto load_ind;
+               case BPF_S_LD_B_IND:
+                       load_order = 0;
+load_ind:
+                       OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
+                       goto load_common;
+               case BPF_S_LDX_IMM:
+                       ctx->seen |= SEEN_X;
+                       emit_mov_i(r_X, k, ctx);
+                       break;
+               case BPF_S_LDX_W_LEN:
+                       ctx->seen |= SEEN_X | SEEN_SKB;
+                       emit(ARM_LDR_I(r_X, r_skb,
+                                      offsetof(struct sk_buff, len)), ctx);
+                       break;
+               case BPF_S_LDX_MEM:
+                       ctx->seen |= SEEN_X | SEEN_MEM_WORD(k);
+                       emit(ARM_LDR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_LDX_B_MSH:
+                       /* x = ((*(frame + k)) & 0xf) << 2; */
+                       ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL;
+                       /* the interpreter should deal with the negative K */
+                       if (k < 0)
+                               return -1;
+                       /* offset in r1: we might have to take the slow path */
+                       emit_mov_i(r_off, k, ctx);
+                       emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
+
+                       /* load in r0: common with the slowpath */
+                       _emit(ARM_COND_HI, ARM_LDRB_R(ARM_R0, r_skb_data,
+                                                     ARM_R1), ctx);
+                       /*
+                        * emit_mov_i() might generate one or two instructions,
+                        * the same holds for emit_blx_r()
+                        */
+                       _emit(ARM_COND_HI, ARM_B(b_imm(i + 1, ctx) - 2), ctx);
+
+                       emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
+                       /* r_off is r1 */
+                       emit_mov_i(ARM_R3, (u32)jit_get_skb_b, ctx);
+                       emit_blx_r(ARM_R3, ctx);
+                       /* check the return value of skb_copy_bits */
+                       emit(ARM_CMP_I(ARM_R1, 0), ctx);
+                       emit_err_ret(ARM_COND_NE, ctx);
+
+                       emit(ARM_AND_I(r_X, ARM_R0, 0x00f), ctx);
+                       emit(ARM_LSL_I(r_X, r_X, 2), ctx);
+                       break;
+               case BPF_S_ST:
+                       ctx->seen |= SEEN_MEM_WORD(k);
+                       emit(ARM_STR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_STX:
+                       update_on_xread(ctx);
+                       ctx->seen |= SEEN_MEM_WORD(k);
+                       emit(ARM_STR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_ALU_ADD_K:
+                       /* A += K */
+                       OP_IMM3(ARM_ADD, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_ADD_X:
+                       update_on_xread(ctx);
+                       emit(ARM_ADD_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_SUB_K:
+                       /* A -= K */
+                       OP_IMM3(ARM_SUB, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_SUB_X:
+                       update_on_xread(ctx);
+                       emit(ARM_SUB_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_MUL_K:
+                       /* A *= K */
+                       emit_mov_i(r_scratch, k, ctx);
+                       emit(ARM_MUL(r_A, r_A, r_scratch), ctx);
+                       break;
+               case BPF_S_ALU_MUL_X:
+                       update_on_xread(ctx);
+                       emit(ARM_MUL(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_DIV_K:
+                       /* current k == reciprocal_value(userspace k) */
+                       emit_mov_i(r_scratch, k, ctx);
+                       /* A = top 32 bits of the product */
+                       emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+                       break;
+               case BPF_S_ALU_DIV_X:
+                       update_on_xread(ctx);
+                       emit(ARM_CMP_I(r_X, 0), ctx);
+                       emit_err_ret(ARM_COND_EQ, ctx);
+                       emit_udiv(r_A, r_A, r_X, ctx);
+                       break;
+               case BPF_S_ALU_OR_K:
+                       /* A |= K */
+                       OP_IMM3(ARM_ORR, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_OR_X:
+                       update_on_xread(ctx);
+                       emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_AND_K:
+                       /* A &= K */
+                       OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_AND_X:
+                       update_on_xread(ctx);
+                       emit(ARM_AND_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_LSH_K:
+                       if (unlikely(k > 31))
+                               return -1;
+                       emit(ARM_LSL_I(r_A, r_A, k), ctx);
+                       break;
+               case BPF_S_ALU_LSH_X:
+                       update_on_xread(ctx);
+                       emit(ARM_LSL_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_RSH_K:
+                       if (unlikely(k > 31))
+                               return -1;
+                       emit(ARM_LSR_I(r_A, r_A, k), ctx);
+                       break;
+               case BPF_S_ALU_RSH_X:
+                       update_on_xread(ctx);
+                       emit(ARM_LSR_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_NEG:
+                       /* A = -A */
+                       emit(ARM_RSB_I(r_A, r_A, 0), ctx);
+                       break;
+               case BPF_S_JMP_JA:
+                       /* pc += K */
+                       emit(ARM_B(b_imm(i + k + 1, ctx)), ctx);
+                       break;
+               case BPF_S_JMP_JEQ_K:
+                       /* pc += (A == K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_EQ;
+                       goto cmp_imm;
+               case BPF_S_JMP_JGT_K:
+                       /* pc += (A > K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_HI;
+                       goto cmp_imm;
+               case BPF_S_JMP_JGE_K:
+                       /* pc += (A >= K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_HS;
+cmp_imm:
+                       imm12 = imm8m(k);
+                       if (imm12 < 0) {
+                               emit_mov_i_no8m(r_scratch, k, ctx);
+                               emit(ARM_CMP_R(r_A, r_scratch), ctx);
+                       } else {
+                               emit(ARM_CMP_I(r_A, imm12), ctx);
+                       }
+cond_jump:
+                       if (inst->jt)
+                               _emit(condt, ARM_B(b_imm(i + inst->jt + 1,
+                                                  ctx)), ctx);
+                       if (inst->jf)
+                               _emit(condt ^ 1, ARM_B(b_imm(i + inst->jf + 1,
+                                                            ctx)), ctx);
+                       break;
+               case BPF_S_JMP_JEQ_X:
+                       /* pc += (A == X) ? pc->jt : pc->jf */
+                       condt   = ARM_COND_EQ;
+                       goto cmp_x;
+               case BPF_S_JMP_JGT_X:
+                       /* pc += (A > X) ? pc->jt : pc->jf */
+                       condt   = ARM_COND_HI;
+                       goto cmp_x;
+               case BPF_S_JMP_JGE_X:
+                       /* pc += (A >= X) ? pc->jt : pc->jf */
+                       condt   = ARM_COND_CS;
+cmp_x:
+                       update_on_xread(ctx);
+                       emit(ARM_CMP_R(r_A, r_X), ctx);
+                       goto cond_jump;
+               case BPF_S_JMP_JSET_K:
+                       /* pc += (A & K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_NE;
+                       /* not set iff all zeroes iff Z==1 iff EQ */
+
+                       imm12 = imm8m(k);
+                       if (imm12 < 0) {
+                               emit_mov_i_no8m(r_scratch, k, ctx);
+                               emit(ARM_TST_R(r_A, r_scratch), ctx);
+                       } else {
+                               emit(ARM_TST_I(r_A, imm12), ctx);
+                       }
+                       goto cond_jump;
+               case BPF_S_JMP_JSET_X:
+                       /* pc += (A & X) ? pc->jt : pc->jf */
+                       update_on_xread(ctx);
+                       condt  = ARM_COND_NE;
+                       emit(ARM_TST_R(r_A, r_X), ctx);
+                       goto cond_jump;
+               case BPF_S_RET_A:
+                       emit(ARM_MOV_R(ARM_R0, r_A), ctx);
+                       goto b_epilogue;
+               case BPF_S_RET_K:
+                       if ((k == 0) && (ctx->ret0_fp_idx < 0))
+                               ctx->ret0_fp_idx = i;
+                       emit_mov_i(ARM_R0, k, ctx);
+b_epilogue:
+                       if (i != ctx->skf->len - 1)
+                               emit(ARM_B(b_imm(prog->len, ctx)), ctx);
+                       break;
+               case BPF_S_MISC_TAX:
+                       /* X = A */
+                       ctx->seen |= SEEN_X;
+                       emit(ARM_MOV_R(r_X, r_A), ctx);
+                       break;
+               case BPF_S_MISC_TXA:
+                       /* A = X */
+                       update_on_xread(ctx);
+                       emit(ARM_MOV_R(r_A, r_X), ctx);
+                       break;
+               case BPF_S_ANC_PROTOCOL:
+                       /* A = ntohs(skb->protocol) */
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                                                 protocol) != 2);
+                       off = offsetof(struct sk_buff, protocol);
+                       emit(ARM_LDRH_I(r_scratch, r_skb, off), ctx);
+                       emit_swap16(r_A, r_scratch, ctx);
+                       break;
+               case BPF_S_ANC_CPU:
+                       /* r_scratch = current_thread_info() */
+                       OP_IMM3(ARM_BIC, r_scratch, ARM_SP, THREAD_SIZE - 1, ctx);
+                       /* A = current_thread_info()->cpu */
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4);
+                       off = offsetof(struct thread_info, cpu);
+                       emit(ARM_LDR_I(r_A, r_scratch, off), ctx);
+                       break;
+               case BPF_S_ANC_IFINDEX:
+                       /* A = skb->dev->ifindex */
+                       ctx->seen |= SEEN_SKB;
+                       off = offsetof(struct sk_buff, dev);
+                       emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
+
+                       emit(ARM_CMP_I(r_scratch, 0), ctx);
+                       emit_err_ret(ARM_COND_EQ, ctx);
+
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+                                                 ifindex) != 4);
+                       off = offsetof(struct net_device, ifindex);
+                       emit(ARM_LDR_I(r_A, r_scratch, off), ctx);
+                       break;
+               case BPF_S_ANC_MARK:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+                       off = offsetof(struct sk_buff, mark);
+                       emit(ARM_LDR_I(r_A, r_skb, off), ctx);
+                       break;
+               case BPF_S_ANC_RXHASH:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+                       off = offsetof(struct sk_buff, rxhash);
+                       emit(ARM_LDR_I(r_A, r_skb, off), ctx);
+                       break;
+               case BPF_S_ANC_QUEUE:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                                                 queue_mapping) != 2);
+                       BUILD_BUG_ON(offsetof(struct sk_buff,
+                                             queue_mapping) > 0xff);
+                       off = offsetof(struct sk_buff, queue_mapping);
+                       emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+                       break;
+               default:
+                       return -1;
+               }
+       }
+
+       /* compute offsets only during the first pass */
+       if (ctx->target == NULL)
+               ctx->offsets[i] = ctx->idx * 4;
+
+       return 0;
+}
+
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+       struct jit_ctx ctx;
+       unsigned tmp_idx;
+       unsigned alloc_size;
+
+       if (!bpf_jit_enable)
+               return;
+
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.skf         = fp;
+       ctx.ret0_fp_idx = -1;
+
+       ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1));
+       if (ctx.offsets == NULL)
+               return;
+
+       /* fake pass to fill in the ctx->seen */
+       if (unlikely(build_body(&ctx)))
+               goto out;
+
+       tmp_idx = ctx.idx;
+       build_prologue(&ctx);
+       ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
+
+#if __LINUX_ARM_ARCH__ < 7
+       tmp_idx = ctx.idx;
+       build_epilogue(&ctx);
+       ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4;
+
+       ctx.idx += ctx.imm_count;
+       if (ctx.imm_count) {
+               ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count);
+               if (ctx.imms == NULL)
+                       goto out;
+       }
+#else
+       /* there's nothing after the epilogue on ARMv7 */
+       build_epilogue(&ctx);
+#endif
+
+       alloc_size = 4 * ctx.idx;
+       ctx.target = module_alloc(max(sizeof(struct work_struct),
+                                     alloc_size));
+       if (unlikely(ctx.target == NULL))
+               goto out;
+
+       ctx.idx = 0;
+       build_prologue(&ctx);
+       build_body(&ctx);
+       build_epilogue(&ctx);
+
+       flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx));
+
+#if __LINUX_ARM_ARCH__ < 7
+       if (ctx.imm_count)
+               kfree(ctx.imms);
+#endif
+
+       if (bpf_jit_enable > 1)
+               print_hex_dump(KERN_INFO, "BPF JIT code: ",
+                              DUMP_PREFIX_ADDRESS, 16, 4, ctx.target,
+                              alloc_size, false);
+
+       fp->bpf_func = (void *)ctx.target;
+out:
+       kfree(ctx.offsets);
+       return;
+}
+
+static void bpf_jit_free_worker(struct work_struct *work)
+{
+       module_free(NULL, work);
+}
+
+void bpf_jit_free(struct sk_filter *fp)
+{
+       struct work_struct *work;
+
+       if (fp->bpf_func != sk_run_filter) {
+               work = (struct work_struct *)fp->bpf_func;
+
+               INIT_WORK(work, bpf_jit_free_worker);
+               schedule_work(work);
+       }
+}
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
new file mode 100644 (file)
index 0000000..99ae5e3
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Just-In-Time compiler for BPF filters on 32bit ARM
+ *
+ * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef PFILTER_OPCODES_ARM_H
+#define PFILTER_OPCODES_ARM_H
+
+#define ARM_R0 0
+#define ARM_R1 1
+#define ARM_R2 2
+#define ARM_R3 3
+#define ARM_R4 4
+#define ARM_R5 5
+#define ARM_R6 6
+#define ARM_R7 7
+#define ARM_R8 8
+#define ARM_R9 9
+#define ARM_R10        10
+#define ARM_FP 11
+#define ARM_IP 12
+#define ARM_SP 13
+#define ARM_LR 14
+#define ARM_PC 15
+
+#define ARM_COND_EQ            0x0
+#define ARM_COND_NE            0x1
+#define ARM_COND_CS            0x2
+#define ARM_COND_HS            ARM_COND_CS
+#define ARM_COND_CC            0x3
+#define ARM_COND_LO            ARM_COND_CC
+#define ARM_COND_MI            0x4
+#define ARM_COND_PL            0x5
+#define ARM_COND_VS            0x6
+#define ARM_COND_VC            0x7
+#define ARM_COND_HI            0x8
+#define ARM_COND_LS            0x9
+#define ARM_COND_GE            0xa
+#define ARM_COND_LT            0xb
+#define ARM_COND_GT            0xc
+#define ARM_COND_LE            0xd
+#define ARM_COND_AL            0xe
+
+/* register shift types */
+#define SRTYPE_LSL             0
+#define SRTYPE_LSR             1
+#define SRTYPE_ASR             2
+#define SRTYPE_ROR             3
+
+#define ARM_INST_ADD_R         0x00800000
+#define ARM_INST_ADD_I         0x02800000
+
+#define ARM_INST_AND_R         0x00000000
+#define ARM_INST_AND_I         0x02000000
+
+#define ARM_INST_BIC_R         0x01c00000
+#define ARM_INST_BIC_I         0x03c00000
+
+#define ARM_INST_B             0x0a000000
+#define ARM_INST_BX            0x012FFF10
+#define ARM_INST_BLX_R         0x012fff30
+
+#define ARM_INST_CMP_R         0x01500000
+#define ARM_INST_CMP_I         0x03500000
+
+#define ARM_INST_LDRB_I                0x05d00000
+#define ARM_INST_LDRB_R                0x07d00000
+#define ARM_INST_LDRH_I                0x01d000b0
+#define ARM_INST_LDR_I         0x05900000
+
+#define ARM_INST_LDM           0x08900000
+
+#define ARM_INST_LSL_I         0x01a00000
+#define ARM_INST_LSL_R         0x01a00010
+
+#define ARM_INST_LSR_I         0x01a00020
+#define ARM_INST_LSR_R         0x01a00030
+
+#define ARM_INST_MOV_R         0x01a00000
+#define ARM_INST_MOV_I         0x03a00000
+#define ARM_INST_MOVW          0x03000000
+#define ARM_INST_MOVT          0x03400000
+
+#define ARM_INST_MUL           0x00000090
+
+#define ARM_INST_POP           0x08bd0000
+#define ARM_INST_PUSH          0x092d0000
+
+#define ARM_INST_ORR_R         0x01800000
+#define ARM_INST_ORR_I         0x03800000
+
+#define ARM_INST_REV           0x06bf0f30
+#define ARM_INST_REV16         0x06bf0fb0
+
+#define ARM_INST_RSB_I         0x02600000
+
+#define ARM_INST_SUB_R         0x00400000
+#define ARM_INST_SUB_I         0x02400000
+
+#define ARM_INST_STR_I         0x05800000
+
+#define ARM_INST_TST_R         0x01100000
+#define ARM_INST_TST_I         0x03100000
+
+#define ARM_INST_UDIV          0x0730f010
+
+#define ARM_INST_UMULL         0x00800090
+
+/* register */
+#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm))
+/* immediate */
+#define _AL3_I(op, rd, rn, imm)        ((op ## _I) | (rd) << 12 | (rn) << 16 | (imm))
+
+#define ARM_ADD_R(rd, rn, rm)  _AL3_R(ARM_INST_ADD, rd, rn, rm)
+#define ARM_ADD_I(rd, rn, imm) _AL3_I(ARM_INST_ADD, rd, rn, imm)
+
+#define ARM_AND_R(rd, rn, rm)  _AL3_R(ARM_INST_AND, rd, rn, rm)
+#define ARM_AND_I(rd, rn, imm) _AL3_I(ARM_INST_AND, rd, rn, imm)
+
+#define ARM_BIC_R(rd, rn, rm)  _AL3_R(ARM_INST_BIC, rd, rn, rm)
+#define ARM_BIC_I(rd, rn, imm) _AL3_I(ARM_INST_BIC, rd, rn, imm)
+
+#define ARM_B(imm24)           (ARM_INST_B | ((imm24) & 0xffffff))
+#define ARM_BX(rm)             (ARM_INST_BX | (rm))
+#define ARM_BLX_R(rm)          (ARM_INST_BLX_R | (rm))
+
+#define ARM_CMP_R(rn, rm)      _AL3_R(ARM_INST_CMP, 0, rn, rm)
+#define ARM_CMP_I(rn, imm)     _AL3_I(ARM_INST_CMP, 0, rn, imm)
+
+#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
+                                | (off))
+#define ARM_LDRB_I(rt, rn, off)        (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \
+                                | (off))
+#define ARM_LDRB_R(rt, rn, rm) (ARM_INST_LDRB_R | (rt) << 12 | (rn) << 16 \
+                                | (rm))
+#define ARM_LDRH_I(rt, rn, off)        (ARM_INST_LDRH_I | (rt) << 12 | (rn) << 16 \
+                                | (((off) & 0xf0) << 4) | ((off) & 0xf))
+
+#define ARM_LDM(rn, regs)      (ARM_INST_LDM | (rn) << 16 | (regs))
+
+#define ARM_LSL_R(rd, rn, rm)  (_AL3_R(ARM_INST_LSL, rd, 0, rn) | (rm) << 8)
+#define ARM_LSL_I(rd, rn, imm) (_AL3_I(ARM_INST_LSL, rd, 0, rn) | (imm) << 7)
+
+#define ARM_LSR_R(rd, rn, rm)  (_AL3_R(ARM_INST_LSR, rd, 0, rn) | (rm) << 8)
+#define ARM_LSR_I(rd, rn, imm) (_AL3_I(ARM_INST_LSR, rd, 0, rn) | (imm) << 7)
+
+#define ARM_MOV_R(rd, rm)      _AL3_R(ARM_INST_MOV, rd, 0, rm)
+#define ARM_MOV_I(rd, imm)     _AL3_I(ARM_INST_MOV, rd, 0, imm)
+
+#define ARM_MOVW(rd, imm)      \
+       (ARM_INST_MOVW | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
+
+#define ARM_MOVT(rd, imm)      \
+       (ARM_INST_MOVT | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
+
+#define ARM_MUL(rd, rm, rn)    (ARM_INST_MUL | (rd) << 16 | (rm) << 8 | (rn))
+
+#define ARM_POP(regs)          (ARM_INST_POP | (regs))
+#define ARM_PUSH(regs)         (ARM_INST_PUSH | (regs))
+
+#define ARM_ORR_R(rd, rn, rm)  _AL3_R(ARM_INST_ORR, rd, rn, rm)
+#define ARM_ORR_I(rd, rn, imm) _AL3_I(ARM_INST_ORR, rd, rn, imm)
+#define ARM_ORR_S(rd, rn, rm, type, rs)        \
+       (ARM_ORR_R(rd, rn, rm) | (type) << 5 | (rs) << 7)
+
+#define ARM_REV(rd, rm)                (ARM_INST_REV | (rd) << 12 | (rm))
+#define ARM_REV16(rd, rm)      (ARM_INST_REV16 | (rd) << 12 | (rm))
+
+#define ARM_RSB_I(rd, rn, imm) _AL3_I(ARM_INST_RSB, rd, rn, imm)
+
+#define ARM_SUB_R(rd, rn, rm)  _AL3_R(ARM_INST_SUB, rd, rn, rm)
+#define ARM_SUB_I(rd, rn, imm) _AL3_I(ARM_INST_SUB, rd, rn, imm)
+
+#define ARM_STR_I(rt, rn, off) (ARM_INST_STR_I | (rt) << 12 | (rn) << 16 \
+                                | (off))
+
+#define ARM_TST_R(rn, rm)      _AL3_R(ARM_INST_TST, 0, rn, rm)
+#define ARM_TST_I(rn, imm)     _AL3_I(ARM_INST_TST, 0, rn, imm)
+
+#define ARM_UDIV(rd, rn, rm)   (ARM_INST_UDIV | (rd) << 16 | (rn) | (rm) << 8)
+
+#define ARM_UMULL(rd_lo, rd_hi, rn, rm)        (ARM_INST_UMULL | (rd_hi) << 16 \
+                                        | (rd_lo) << 12 | (rm) << 8 | rn)
+
+#endif /* PFILTER_OPCODES_ARM_H */
index cc60acde84d9272697d5b3ed70656966f4b086c5..2782ebcc2ed3750b17b1ee90ebc4e9abe299d18d 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/compiler.h>
 #include <linux/string.h>
-#include <asm/system.h>
 
 /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
 static void resetFPA11(void)
index 4efe392859ee943ba31f1ae0450fb9669a8cea47..88215ad031a28efaf83a2b9281227c3d66a801f8 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/hardware/iop3xx.h>
index 72768356447ae9b8b3aa6b56314cc172708d998d..0da42058a20f1d590c58660c377152a2e43fa8c6 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach/pci.h>
 #include <asm/hardware/iop3xx.h>
index 6a85a0c502e68a9a3ca0d9400702e944f69d449a..33fa699a4d28ff88104cd36c7094ef00f6caeefb 100644 (file)
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <asm/hardware/iop3xx.h>
+#include <asm/system_misc.h>
 #include <mach/hardware.h>
 
 void iop3xx_restart(char mode, const char *cmd)
index a599f01f8b92e7e567f97f4ca4227efa6d3bcb29..0630513554def1f851ea708fabd484dbf50deec6 100644 (file)
 
 #include <asm/sizes.h>
 
-#ifdef __ASSEMBLER__
-#define IOMEM(addr)    (addr)
-#else
-#define IOMEM(addr)    ((void __force __iomem *)(addr))
-#endif
+#define addr_in_module(addr, mod) \
+       ((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
 
 #define IMX_IO_P2V_MODULE(addr, module)                                        \
        (((addr) - module ## _BASE_ADDR) < module ## _SIZE ?            \
diff --git a/arch/arm/plat-mxc/include/mach/io.h b/arch/arm/plat-mxc/include/mach/io.h
deleted file mode 100644 (file)
index 338300b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_MXC_IO_H__
-#define __ASM_ARCH_MXC_IO_H__
-
-/* Allow IO space to be anywhere in the memory */
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __arch_ioremap __imx_ioremap
-#define __arch_iounmap __iounmap
-
-#define addr_in_module(addr, mod) \
-       ((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
-
-extern void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int);
-
-static inline void __iomem *
-__imx_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
-{
-       if (imx_ioremap != NULL)
-               return imx_ioremap(phys_addr, size, mtype);
-       else
-               return __arm_ioremap(phys_addr, size, mtype);
-}
-
-/* io address mapping macro */
-#define __io(a)                __typesafe_io(a)
-
-#define __mem_pci(a)   (a)
-
-#endif
index f30dcacbbd0aef44b68a26cbd82563b7b8320a8e..1996c3e3b8fe632ee51c12ba2e528b435007d4a7 100644 (file)
@@ -25,8 +25,8 @@
 
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <asm/system_misc.h>
 #include <asm/proc-fns.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
index bca4914b4b9dab344f19c6fd6eb84a084e91030d..4c48c8b60b54e4672a0ff10c85d4a6fe93c9d8d6 100644 (file)
@@ -23,7 +23,6 @@ config HAS_MTU
 config NOMADIK_MTU_SCHED_CLOCK
        bool
        depends on HAS_MTU
-       select HAVE_SCHED_CLOCK
        help
          Use the Multi Timer Unit as the sched_clock.
 
index fd0ee84c45d1bc66b51e0a5527f75d9981040eeb..9ff93b06568695f04822dd066f5c78a35beca3e7 100644 (file)
@@ -200,8 +200,7 @@ dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
        sg.dma_address = addr;
        sg.length = size;
 
-       return chan->device->device_prep_slave_sg(chan, &sg, 1,
-                                                 direction, flags);
+       return dmaengine_prep_slave_sg(chan, &sg, 1, direction, flags);
 }
 
 #else
index 61a1ec2a6af4273e1c7693fdd4191ba3c92a0616..39407cbe34c65ab0308a5b1585ad896d5c5f3c2f 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
index 74300ae29b71e72c0ec1052b0e38094dafe260fe..ecdb3da0dea93704086df1f83dff342813c3afd3 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <plat/dma.h>
 
index cb75b657b04b73e214cb32ee6edf8149d2c78a33..b8a96c6a1a30773d6231f3fe100539168a7bc2ca 100644 (file)
@@ -218,30 +218,14 @@ extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
 /*-------------------------------------------------------------------------*/
 
-/* Wrappers for "new style" GPIO calls, using the new infrastructure
+/*
+ * Wrappers for "new style" GPIO calls, using the new infrastructure
  * which lets us plug in FPGA, I2C, and other implementations.
- * *
+ *
  * The original OMAP-specific calls should eventually be removed.
  */
 
 #include <linux/errno.h>
 #include <asm-generic/gpio.h>
 
-static inline int irq_to_gpio(unsigned irq)
-{
-       int tmp;
-
-       /* omap1 SOC mpuio */
-       if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16)))
-               return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES;
-
-       /* SOC gpio */
-       tmp = irq - IH_GPIO_BASE;
-       if (tmp < OMAP_MAX_GPIO_LINES)
-               return tmp;
-
-       /* we don't supply reverse mappings for non-SOC gpios */
-       return -EIO;
-}
-
 #endif
index 537b05ae1f51aaba0380b6186b7be9542ac9c667..e897978371c2719167eb7bfbe2625dc5d7bc6fdf 100644 (file)
 #endif
 #include <plat/serial.h>
 
-#ifdef __ASSEMBLER__
-#define IOMEM(x)               (x)
-#else
-#define IOMEM(x)               ((void __force __iomem *)(x))
-#endif
-
 /*
  * ---------------------------------------------------------------------------
  * Common definitions for all OMAP processors
index f75946c3293d2bd26b0de35b8f253c0ed832eb3d..7a38750c0079088dafc76dd64f7d8135d1369d39 100644 (file)
@@ -137,8 +137,6 @@ struct omap_mmc_platform_data {
                int (*set_power)(struct device *dev, int slot,
                                 int power_on, int vdd);
                int (*get_ro)(struct device *dev, int slot);
-               int (*set_sleep)(struct device *dev, int slot, int sleep,
-                                int vdd, int cardsleep);
                void (*remux)(struct device *dev, int slot, int power_on);
                /* Call back before enabling / disabling regulators */
                void (*before_set_reg)(struct device *dev, int slot,
index 925b12b500dc7ecca1f8c508acdbeb9ecee38c53..9bb978ecd884ac3a378a40a03f9c59b494181929 100644 (file)
@@ -16,7 +16,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <mach/io.h>
 
 /* SDRC register offsets - read/write with sdrc_{read,write}_reg() */
 
index d0fc9f4dc155b1bc2e32e256004c36e0ffaca9c7..762eeb0626c128fd5c40bbb97daff230ef881466 100644 (file)
@@ -112,7 +112,6 @@ extern int omap4430_phy_suspend(struct device *dev, int suspend);
  */
 
 #define OMAP2_L4_IO_OFFSET     0xb2000000
-#define IOMEM(x)               ((void __force __iomem *)(x))
 #define OMAP2_L4_IO_ADDRESS(pa)        IOMEM((pa) + OMAP2_L4_IO_OFFSET)
 
 static inline u8 omap_readb(u32 pa)
index 2d3c19d7c7b1cd69a29c1796a913ee6e5a681c0c..79ef102e3b2bfdbd2e9b278315779e16ffbbaa39 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/errno.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/memory.h>
 #include <mach/hardware.h>
index 32a09931350c16ebc5d0d7bc0d823d5ccc0dbfbc..0db73ae646bcfb616242b04340eb528ca70551bb 100644 (file)
@@ -35,6 +35,7 @@
 #include <mach/regs-clock.h>
 #include <asm/irq.h>
 #include <asm/cacheflush.h>
+#include <asm/system_info.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 2bab4c99a2342218fff937cbe5bc701149f76d0c..28f898f75380a8ff39036805afdc5b5d40803df8 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/errno.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
index 81c06d44c11e4f55cdcea71a60b2673d0e828c07..46b426e8aff599636314f3d59bc364dd138e09b9 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #include <mach/map.h>
 #include <plat/cpu.h>
index 301d9c319d0bb69b590eb63cc5e4b2319a466cb1..eb9f4f5340060d432f7fd6741a3acfc6fbfa2dbc 100644 (file)
@@ -79,11 +79,11 @@ static int samsung_dmadev_prepare(unsigned ch,
                            info->len, offset_in_page(info->buf));
                sg_dma_address(&sg) = info->buf;
 
-               desc = chan->device->device_prep_slave_sg(chan,
+               desc = dmaengine_prep_slave_sg(chan,
                        &sg, 1, info->direction, DMA_PREP_INTERRUPT);
                break;
        case DMA_CYCLIC:
-               desc = chan->device->device_prep_dma_cyclic(chan,
+               desc = dmaengine_prep_dma_cyclic(chan,
                        info->buf, info->len, info->period, info->direction);
                break;
        default:
index e3bb806bbafe2397a1d6072a3e77306591eb914c..4dcb11c3d894013e93d9a5c799e95ec5cc0a9582 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 
index 66d677225d155c0e4a09c6d1a8a54f22f1ad8122..70187d763e26f7ff0e5c32dee2f483db03510e21 100644 (file)
 #ifndef __PLAT_HARDWARE_H
 #define __PLAT_HARDWARE_H
 
-#ifndef __ASSEMBLY__
-#define IOMEM(x)       ((void __iomem __force *)(x))
-#else
-#define IOMEM(x)       (x)
-#endif
-
 #endif /* __PLAT_HARDWARE_H */
diff --git a/arch/arm/plat-spear/include/plat/io.h b/arch/arm/plat-spear/include/plat/io.h
deleted file mode 100644 (file)
index 4d4ba82..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/plat-spear/include/plat/io.h
- *
- * IO definitions for SPEAr platform
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_IO_H
-#define __PLAT_IO_H
-
-#define IO_SPACE_LIMIT         0xFFFFFFFF
-
-#define __io(a)                        __typesafe_io(a)
-#define __mem_pci(a)           (a)
-
-#endif /* __PLAT_IO_H */
index 2b4e3d82957c9c770a073af5f73bdde3b943fc8d..16f203e78d89504d268f8c45260bd6fe06b0b142 100644 (file)
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 #include <linux/io.h>
+#include <asm/system_misc.h>
 #include <asm/hardware/sp810.h>
 #include <mach/hardware.h>
 #include <mach/generic.h>
index 52353beb369d635ebfd51de7b2d0fa3bf6b21966..043f7b02a9e709b239d81d2715ab0258748986d3 100644 (file)
@@ -11,7 +11,6 @@ config PLAT_VERSATILE_LEDS
        depends on ARCH_REALVIEW || ARCH_VERSATILE
 
 config PLAT_VERSATILE_SCHED_CLOCK
-       def_bool y if !ARCH_INTEGRATOR_AP
-       select HAVE_SCHED_CLOCK
+       def_bool y
 
 endif
index 8f3ccddbdafd07787b2a57b02778f4c59046cae9..858748eaa144f91c7f9b4c88fbc8bb83a8d419d7 100644 (file)
@@ -18,7 +18,9 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 
+#include <asm/cp15.h>
 #include <asm/cputype.h>
+#include <asm/system_info.h>
 #include <asm/thread_notify.h>
 #include <asm/vfp.h>
 
index e0ac2631c87e3166d52c13d879c622f0bab75c4e..61407279208ab43b8af98f410ce3e56a88ce198e 100644 (file)
@@ -15,7 +15,7 @@
 #define __ASM_AVR32_ATOMIC_H
 
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
diff --git a/arch/avr32/include/asm/barrier.h b/arch/avr32/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..808001c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004-2006 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.
+ */
+#ifndef __ASM_AVR32_BARRIER_H
+#define __ASM_AVR32_BARRIER_H
+
+#define mb()                   asm volatile("" : : : "memory")
+#define rmb()                  mb()
+#define wmb()                  asm volatile("sync 0" : : : "memory")
+#define read_barrier_depends()  do { } while(0)
+#define set_mb(var, value)      do { var = value; mb(); } while(0)
+
+#ifdef CONFIG_SMP
+# error "The AVR32 port does not support SMP"
+#else
+# define smp_mb()              barrier()
+# define smp_rmb()             barrier()
+# define smp_wmb()             barrier()
+# define smp_read_barrier_depends() do { } while(0)
+#endif
+
+
+#endif /* __ASM_AVR32_BARRIER_H */
index b70c19bab63af141d8815e1ec76fb96f3b06b63b..ebe7ad3f490b3eb56668ffece9b3306c78a98964 100644 (file)
@@ -13,7 +13,6 @@
 #endif
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 /*
  * clear_bit() doesn't provide any barrier for the compiler
index 2aa373cc61b58e7f7c4807837a60a0c687269f27..85a92d099adbf4edb735d07b8755809c50dbe267 100644 (file)
@@ -70,4 +70,9 @@
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+void die(const char *str, struct pt_regs *regs, long err);
+void _exception(long signr, struct pt_regs *regs, int code,
+               unsigned long addr);
+
 #endif /* __ASM_AVR32_BUG_H */
diff --git a/arch/avr32/include/asm/cmpxchg.h b/arch/avr32/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..962a6ae
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc.
+ *
+ * But use these as seldom as possible since they are slower than
+ * regular operations.
+ *
+ * Copyright (C) 2004-2006 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.
+ */
+#ifndef __ASM_AVR32_CMPXCHG_H
+#define __ASM_AVR32_CMPXCHG_H
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long xchg_u32(u32 val, volatile u32 *m)
+{
+       u32 ret;
+
+       asm volatile("xchg %[ret], %[m], %[val]"
+                       : [ret] "=&r"(ret), "=m"(*m)
+                       : "m"(*m), [m] "r"(m), [val] "r"(val)
+                       : "memory");
+       return ret;
+}
+
+static inline unsigned long __xchg(unsigned long x,
+                                      volatile void *ptr,
+                                      int size)
+{
+       switch(size) {
+       case 4:
+               return xchg_u32(x, ptr);
+       default:
+               __xchg_called_with_bad_pointer();
+               return x;
+       }
+}
+
+static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
+                                         unsigned long new)
+{
+       __u32 ret;
+
+       asm volatile(
+               "1:     ssrf    5\n"
+               "       ld.w    %[ret], %[m]\n"
+               "       cp.w    %[ret], %[old]\n"
+               "       brne    2f\n"
+               "       stcond  %[m], %[new]\n"
+               "       brne    1b\n"
+               "2:\n"
+               : [ret] "=&r"(ret), [m] "=m"(*m)
+               : "m"(m), [old] "ir"(old), [new] "r"(new)
+               : "memory", "cc");
+       return ret;
+}
+
+extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
+        volatile int * m, unsigned long old, unsigned long new);
+#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+       }
+
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, old, new)                                 \
+       ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \
+                                  (unsigned long)(new),        \
+                                  sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+#define cmpxchg_local(ptr, old, new)                                   \
+       ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old),   \
+                                  (unsigned long)(new),                \
+                                  sizeof(*(ptr))))
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* __ASM_AVR32_CMPXCHG_H */
diff --git a/arch/avr32/include/asm/exec.h b/arch/avr32/include/asm/exec.h
new file mode 100644 (file)
index 0000000..f467be8
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2004-2006 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.
+ */
+#ifndef __ASM_AVR32_EXEC_H
+#define __ASM_AVR32_EXEC_H
+
+#define arch_align_stack(x)    (x)
+
+#endif /* __ASM_AVR32_EXEC_H */
index fe0c0c014389934df839a35b03b075f6e02cd631..74667bfc88cc7676e4c43332b40705908c747021 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long   __kernel_ino_t;
 typedef unsigned short  __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short  __kernel_nlink_t;
-typedef long            __kernel_off_t;
-typedef int             __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short  __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned long  __kernel_size_t;
 typedef long           __kernel_ssize_t;
 typedef int             __kernel_ptrdiff_t;
-typedef long            __kernel_time_t;
-typedef long            __kernel_suseconds_t;
-typedef long            __kernel_clock_t;
-typedef int             __kernel_timer_t;
-typedef int             __kernel_clockid_t;
-typedef int             __kernel_daddr_t;
-typedef char *          __kernel_caddr_t;
-typedef unsigned short  __kernel_uid16_t;
-typedef unsigned short  __kernel_gid16_t;
-typedef unsigned int    __kernel_uid32_t;
-typedef unsigned int    __kernel_gid32_t;
+#define __kernel_size_t __kernel_size_t
 
 typedef unsigned short  __kernel_old_uid_t;
 typedef unsigned short  __kernel_old_gid_t;
-typedef unsigned short  __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long       __kernel_loff_t;
-#endif
-
-typedef struct {
-    int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef  __FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-    unsigned long __tmp = __fd / __NFDBITS;
-    unsigned long __rem = __fd % __NFDBITS;
-    __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef  __FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-    unsigned long __tmp = __fd / __NFDBITS;
-    unsigned long __rem = __fd % __NFDBITS;
-    __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
+#define __kernel_old_uid_t __kernel_old_uid_t
 
+typedef unsigned short  __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#undef  __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
-    unsigned long __tmp = __fd / __NFDBITS;
-    unsigned long __rem = __fd % __NFDBITS;
-    return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef  __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
-    unsigned long *__tmp = __p->fds_bits;
-    int __i;
-
-    if (__builtin_constant_p(__FDSET_LONGS)) {
-        switch (__FDSET_LONGS) {
-            case 16:
-                __tmp[ 0] = 0; __tmp[ 1] = 0;
-                __tmp[ 2] = 0; __tmp[ 3] = 0;
-                __tmp[ 4] = 0; __tmp[ 5] = 0;
-                __tmp[ 6] = 0; __tmp[ 7] = 0;
-                __tmp[ 8] = 0; __tmp[ 9] = 0;
-                __tmp[10] = 0; __tmp[11] = 0;
-                __tmp[12] = 0; __tmp[13] = 0;
-                __tmp[14] = 0; __tmp[15] = 0;
-                return;
-
-            case 8:
-                __tmp[ 0] = 0; __tmp[ 1] = 0;
-                __tmp[ 2] = 0; __tmp[ 3] = 0;
-                __tmp[ 4] = 0; __tmp[ 5] = 0;
-                __tmp[ 6] = 0; __tmp[ 7] = 0;
-                return;
-
-            case 4:
-                __tmp[ 0] = 0; __tmp[ 1] = 0;
-                __tmp[ 2] = 0; __tmp[ 3] = 0;
-                return;
-        }
-    }
-    __i = __FDSET_LONGS;
-    while (__i) {
-        __i--;
-        *__tmp = 0;
-        __tmp++;
-    }
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif /* __ASM_AVR32_POSIX_TYPES_H */
diff --git a/arch/avr32/include/asm/special_insns.h b/arch/avr32/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..f922218
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2004-2006 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.
+ */
+#ifndef __ASM_AVR32_SPECIAL_INSNS_H
+#define __ASM_AVR32_SPECIAL_INSNS_H
+
+#define nop() asm volatile("nop")
+
+#endif /* __ASM_AVR32_SPECIAL_INSNS_H */
diff --git a/arch/avr32/include/asm/switch_to.h b/arch/avr32/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..9a8e9d5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004-2006 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.
+ */
+#ifndef __ASM_AVR32_SWITCH_TO_H
+#define __ASM_AVR32_SWITCH_TO_H
+
+/*
+ * Help PathFinder and other Nexus-compliant debuggers keep track of
+ * the current PID by emitting an Ownership Trace Message each time we
+ * switch task.
+ */
+#ifdef CONFIG_OWNERSHIP_TRACE
+#include <asm/ocd.h>
+#define finish_arch_switch(prev)                       \
+       do {                                            \
+               ocd_write(PID, prev->pid);              \
+               ocd_write(PID, current->pid);           \
+       } while(0)
+#endif
+
+/*
+ * switch_to(prev, next, last) should switch from task `prev' to task
+ * `next'. `prev' will never be the same as `next'.
+ *
+ * We just delegate everything to the __switch_to assembly function,
+ * which is implemented in arch/avr32/kernel/switch_to.S
+ *
+ * mb() tells GCC not to cache `current' across this call.
+ */
+struct cpu_context;
+struct task_struct;
+extern struct task_struct *__switch_to(struct task_struct *,
+                                      struct cpu_context *,
+                                      struct cpu_context *);
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               last = __switch_to(prev, &prev->thread.cpu_context + 1, \
+                                  &next->thread.cpu_context);          \
+       } while (0)
+
+
+#endif /* __ASM_AVR32_SWITCH_TO_H */
diff --git a/arch/avr32/include/asm/system.h b/arch/avr32/include/asm/system.h
deleted file mode 100644 (file)
index 62d9ded..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2004-2006 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.
- */
-#ifndef __ASM_AVR32_SYSTEM_H
-#define __ASM_AVR32_SYSTEM_H
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-
-#include <asm/ptrace.h>
-#include <asm/sysreg.h>
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-#define nop() asm volatile("nop")
-
-#define mb()                   asm volatile("" : : : "memory")
-#define rmb()                  mb()
-#define wmb()                  asm volatile("sync 0" : : : "memory")
-#define read_barrier_depends()  do { } while(0)
-#define set_mb(var, value)      do { var = value; mb(); } while(0)
-
-/*
- * Help PathFinder and other Nexus-compliant debuggers keep track of
- * the current PID by emitting an Ownership Trace Message each time we
- * switch task.
- */
-#ifdef CONFIG_OWNERSHIP_TRACE
-#include <asm/ocd.h>
-#define finish_arch_switch(prev)                       \
-       do {                                            \
-               ocd_write(PID, prev->pid);              \
-               ocd_write(PID, current->pid);           \
-       } while(0)
-#endif
-
-/*
- * switch_to(prev, next, last) should switch from task `prev' to task
- * `next'. `prev' will never be the same as `next'.
- *
- * We just delegate everything to the __switch_to assembly function,
- * which is implemented in arch/avr32/kernel/switch_to.S
- *
- * mb() tells GCC not to cache `current' across this call.
- */
-struct cpu_context;
-struct task_struct;
-extern struct task_struct *__switch_to(struct task_struct *,
-                                      struct cpu_context *,
-                                      struct cpu_context *);
-#define switch_to(prev, next, last)                                    \
-       do {                                                            \
-               last = __switch_to(prev, &prev->thread.cpu_context + 1, \
-                                  &next->thread.cpu_context);          \
-       } while (0)
-
-#ifdef CONFIG_SMP
-# error "The AVR32 port does not support SMP"
-#else
-# define smp_mb()              barrier()
-# define smp_rmb()             barrier()
-# define smp_wmb()             barrier()
-# define smp_read_barrier_depends() do { } while(0)
-#endif
-
-#include <linux/irqflags.h>
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long xchg_u32(u32 val, volatile u32 *m)
-{
-       u32 ret;
-
-       asm volatile("xchg %[ret], %[m], %[val]"
-                       : [ret] "=&r"(ret), "=m"(*m)
-                       : "m"(*m), [m] "r"(m), [val] "r"(val)
-                       : "memory");
-       return ret;
-}
-
-static inline unsigned long __xchg(unsigned long x,
-                                      volatile void *ptr,
-                                      int size)
-{
-       switch(size) {
-       case 4:
-               return xchg_u32(x, ptr);
-       default:
-               __xchg_called_with_bad_pointer();
-               return x;
-       }
-}
-
-static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
-                                         unsigned long new)
-{
-       __u32 ret;
-
-       asm volatile(
-               "1:     ssrf    5\n"
-               "       ld.w    %[ret], %[m]\n"
-               "       cp.w    %[ret], %[old]\n"
-               "       brne    2f\n"
-               "       stcond  %[m], %[new]\n"
-               "       brne    1b\n"
-               "2:\n"
-               : [ret] "=&r"(ret), [m] "=m"(*m)
-               : "m"(m), [old] "ir"(old), [new] "r"(new)
-               : "memory", "cc");
-       return ret;
-}
-
-extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
-        volatile int * m, unsigned long old, unsigned long new);
-#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-       }
-
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr, old, new)                                 \
-       ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \
-                                  (unsigned long)(new),        \
-                                  sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-#define cmpxchg_local(ptr, old, new)                                   \
-       ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old),   \
-                                  (unsigned long)(new),                \
-                                  sizeof(*(ptr))))
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-struct pt_regs;
-void die(const char *str, struct pt_regs *regs, long err);
-void _exception(long signr, struct pt_regs *regs, int code,
-               unsigned long addr);
-
-#define arch_align_stack(x)    (x)
-
-#endif /* __ASM_AVR32_SYSTEM_H */
index 889c544688ca020c4d99f1b3e5d989c8f002308d..0445c4fd67e311e864cf6f9d8e70f4ef3bb530f6 100644 (file)
@@ -1351,7 +1351,6 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
                goto fail;
 
        slave->sdata.dma_dev = &dw_dmac0_device.dev;
-       slave->sdata.reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
        slave->sdata.cfg_hi = (DWC_CFGH_SRC_PER(0)
                                | DWC_CFGH_DST_PER(1));
        slave->sdata.cfg_lo &= ~(DWC_CFGL_HS_DST_POL
@@ -2046,27 +2045,19 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,
        /* Check if DMA slave interface for capture should be configured. */
        if (flags & AC97C_CAPTURE) {
                rx_dws->dma_dev = &dw_dmac0_device.dev;
-               rx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT;
                rx_dws->cfg_hi = DWC_CFGH_SRC_PER(3);
                rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
                rx_dws->src_master = 0;
                rx_dws->dst_master = 1;
-               rx_dws->src_msize = DW_DMA_MSIZE_1;
-               rx_dws->dst_msize = DW_DMA_MSIZE_1;
-               rx_dws->fc = DW_DMA_FC_D_P2M;
        }
 
        /* Check if DMA slave interface for playback should be configured. */
        if (flags & AC97C_PLAYBACK) {
                tx_dws->dma_dev = &dw_dmac0_device.dev;
-               tx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT;
                tx_dws->cfg_hi = DWC_CFGH_DST_PER(4);
                tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
                tx_dws->src_master = 0;
                tx_dws->dst_master = 1;
-               tx_dws->src_msize = DW_DMA_MSIZE_1;
-               tx_dws->dst_msize = DW_DMA_MSIZE_1;
-               tx_dws->fc = DW_DMA_FC_D_M2P;
        }
 
        if (platform_device_add_data(pdev, data,
@@ -2136,14 +2127,10 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data)
        dws = &data->dws;
 
        dws->dma_dev = &dw_dmac0_device.dev;
-       dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
        dws->cfg_hi = DWC_CFGH_DST_PER(2);
        dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
        dws->src_master = 0;
        dws->dst_master = 1;
-       dws->src_msize = DW_DMA_MSIZE_1;
-       dws->dst_msize = DW_DMA_MSIZE_1;
-       dws->fc = DW_DMA_FC_D_M2P;
 
        if (platform_device_add_data(pdev, data,
                                sizeof(struct atmel_abdac_pdata)))
index 627743326253f553e2da7fc2d7f95f5c9d809c28..18b765629a0c8e95625976f91a84a0ac69659e03 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/export.h>
-#include <asm/system.h>
 
 static struct clk *cpuclk;
 
index a9b38967f70365309e98d04f85da2414808aa756..4bba58561d5c887a18ec0f4032fa507df5669c2a 100644 (file)
@@ -14,11 +14,4 @@ struct mci_dma_data {
 #define        slave_data_ptr(s)       (&(s)->sdata)
 #define find_slave_dev(s)      ((s)->sdata.dma_dev)
 
-#define        setup_dma_addr(s, t, r) do {            \
-       if (s) {                                \
-               (s)->sdata.tx_reg = (t);        \
-               (s)->sdata.rx_reg = (r);        \
-       }                                       \
-} while (0)
-
 #endif /* __MACH_ATMEL_MCI_H */
index a3e9b3c4845a50f0fc53bf164923a084650f5c17..f74b7809e089d0bb404f5ea9c0433dbad52212af 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 
 #include <asm/sysreg.h>
-#include <asm/system.h>
 
 #define AVR32_PERFCTR_IRQ_GROUP        0
 #define AVR32_PERFCTR_IRQ_LINE 1
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
deleted file mode 100644 (file)
index a7f4057..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
-#include <asm/barrier.h>
-#include <asm/cmpxchg.h>
-#include <asm/exec.h>
-#include <asm/switch_to.h>
index 3c64b2894c13ffcd589aa877a008c16885ad67b8..1c3ccd416d50ad374d05331ea547f6835fcbab10 100644 (file)
@@ -11,7 +11,7 @@ config TMS320C6X
        select HAVE_DMA_API_DEBUG
        select HAVE_GENERIC_HARDIRQS
        select HAVE_MEMBLOCK
-       select HAVE_SPARSE_IRQ
+       select SPARSE_IRQ
        select IRQ_DOMAIN
        select OF
        select OF_EARLY_FLATTREE
index 13dcf78adf9108150497f57dcbe8aeeef30604cb..3af601e31e66ea5180ee498b04009c431f33e989 100644 (file)
@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
 generic-y += atomic.h
 generic-y += auxvec.h
 generic-y += bitsperlong.h
-generic-y += bug.h
 generic-y += bugs.h
 generic-y += cputime.h
 generic-y += current.h
diff --git a/arch/c6x/include/asm/barrier.h b/arch/c6x/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..538240e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  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.
+ */
+#ifndef _ASM_C6X_BARRIER_H
+#define _ASM_C6X_BARRIER_H
+
+#define nop()                    asm("NOP\n");
+
+#define mb()                     barrier()
+#define rmb()                    barrier()
+#define wmb()                    barrier()
+#define set_mb(var, value)       do { var = value;  mb(); } while (0)
+#define set_wmb(var, value)      do { var = value; wmb(); } while (0)
+
+#define smp_mb()                barrier()
+#define smp_rmb()               barrier()
+#define smp_wmb()               barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+
+#endif /* _ASM_C6X_BARRIER_H */
index 39ab7e874d9621708e238933b1df9b5a4f4248c4..0bec7e5036a85304415455b0857d5312f7e4cd2c 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 /*
diff --git a/arch/c6x/include/asm/bug.h b/arch/c6x/include/asm/bug.h
new file mode 100644 (file)
index 0000000..8d59933
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  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.
+ */
+#ifndef _ASM_C6X_BUG_H
+#define _ASM_C6X_BUG_H
+
+#include <linux/linkage.h>
+#include <asm-generic/bug.h>
+
+struct pt_regs;
+
+extern void die(char *str, struct pt_regs *fp, int nr);
+extern asmlinkage int process_exception(struct pt_regs *regs);
+extern asmlinkage void enable_exception(void);
+
+#endif /* _ASM_C6X_BUG_H */
diff --git a/arch/c6x/include/asm/cmpxchg.h b/arch/c6x/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..b27c8ce
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  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.
+ */
+#ifndef _ASM_C6X_CMPXCHG_H
+#define _ASM_C6X_CMPXCHG_H
+
+#include <linux/irqflags.h>
+
+/*
+ * Misc. functions
+ */
+static inline unsigned int __xchg(unsigned int x, volatile void *ptr, int size)
+{
+       unsigned int tmp;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               tmp = 0;
+               tmp = *((unsigned char *) ptr);
+               *((unsigned char *) ptr) = (unsigned char) x;
+               break;
+       case 2:
+               tmp = 0;
+               tmp = *((unsigned short *) ptr);
+               *((unsigned short *) ptr) = x;
+               break;
+       case 4:
+               tmp = 0;
+               tmp = *((unsigned int *) ptr);
+               *((unsigned int *) ptr) = x;
+               break;
+       }
+       local_irq_restore(flags);
+       return tmp;
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned int)(x), (void *) (ptr), \
+                                   sizeof(*(ptr))))
+#define tas(ptr)    xchg((ptr), 1)
+
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),             \
+                                                    (unsigned long)(o), \
+                                                    (unsigned long)(n), \
+                                                    sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif /* _ASM_C6X_CMPXCHG_H */
diff --git a/arch/c6x/include/asm/exec.h b/arch/c6x/include/asm/exec.h
new file mode 100644 (file)
index 0000000..0fea482
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_C6X_EXEC_H
+#define _ASM_C6X_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_C6X_EXEC_H */
index 77ecbded1f370d07b5d736c22dde0b2a52a29222..3ff7fab956ba1c2158f087a59050f8c45006f25a 100644 (file)
@@ -129,4 +129,13 @@ extern unsigned long get_wchan(struct task_struct *p);
 
 extern const struct seq_operations cpuinfo_op;
 
+/* Reset the board */
+#define HARD_RESET_NOW()
+
+extern unsigned int c6x_core_freq;
+
+
+extern void (*c6x_restart)(void);
+extern void (*c6x_halt)(void);
+
 #endif /* ASM_C6X_PROCESSOR_H */
index 1808f279f82e3509c4bdfd6aa05d95e8b2c03f37..a01e31896fa90937dec74fa746e6745c72a94891 100644 (file)
@@ -27,6 +27,7 @@ extern unsigned int c6x_devstat;
 extern unsigned char c6x_fuse_mac[6];
 
 extern void machine_init(unsigned long dt_ptr);
+extern void time_init(void);
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_C6X_SETUP_H */
diff --git a/arch/c6x/include/asm/special_insns.h b/arch/c6x/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..59672bc
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  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.
+ */
+#ifndef _ASM_C6X_SPECIAL_INSNS_H
+#define _ASM_C6X_SPECIAL_INSNS_H
+
+
+#define get_creg(reg) \
+       ({ unsigned int __x; \
+          asm volatile ("mvc .s2 " #reg ",%0\n" : "=b"(__x)); __x; })
+
+#define set_creg(reg, v) \
+       do { unsigned int __x = (unsigned int)(v); \
+               asm volatile ("mvc .s2 %0," #reg "\n" : : "b"(__x)); \
+       } while (0)
+
+#define or_creg(reg, n) \
+       do { unsigned __x, __n = (unsigned)(n);           \
+               asm volatile ("mvc .s2 " #reg ",%0\n"     \
+                             "or  .l2 %1,%0,%0\n"        \
+                             "mvc .s2 %0," #reg "\n"     \
+                             "nop\n"                     \
+                             : "=&b"(__x) : "b"(__n));   \
+       } while (0)
+
+#define and_creg(reg, n) \
+       do { unsigned __x, __n = (unsigned)(n);           \
+               asm volatile ("mvc .s2 " #reg ",%0\n"     \
+                             "and .l2 %1,%0,%0\n"        \
+                             "mvc .s2 %0," #reg "\n"     \
+                             "nop\n"    \
+                             : "=&b"(__x) : "b"(__n));   \
+       } while (0)
+
+#define get_coreid() (get_creg(DNUM) & 0xff)
+
+/* Set/get IST */
+#define set_ist(x)     set_creg(ISTP, x)
+#define get_ist()       get_creg(ISTP)
+
+/*
+ * Exception management
+ */
+#define disable_exception()
+#define get_except_type()        get_creg(EFR)
+#define ack_exception(type)      set_creg(ECR, 1 << (type))
+#define get_iexcept()            get_creg(IERR)
+#define set_iexcept(mask)        set_creg(IERR, (mask))
+
+#define _extu(x, s, e)                                                 \
+       ({      unsigned int __x;                                       \
+               asm volatile ("extu .S2 %3,%1,%2,%0\n" :                \
+                             "=b"(__x) : "n"(s), "n"(e), "b"(x));      \
+              __x; })
+
+#endif /* _ASM_C6X_SPECIAL_INSNS_H */
diff --git a/arch/c6x/include/asm/switch_to.h b/arch/c6x/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..af6c71f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  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.
+ */
+#ifndef _ASM_C6X_SWITCH_TO_H
+#define _ASM_C6X_SWITCH_TO_H
+
+#include <linux/linkage.h>
+
+#define prepare_to_switch()    do { } while (0)
+
+struct task_struct;
+struct thread_struct;
+asmlinkage void *__switch_to(struct thread_struct *prev,
+                            struct thread_struct *next,
+                            struct task_struct *tsk);
+
+#define switch_to(prev, next, last)                            \
+       do {                                                    \
+               current->thread.wchan = (u_long) __builtin_return_address(0); \
+               (last) = __switch_to(&(prev)->thread,           \
+                                    &(next)->thread, (prev));  \
+               mb();                                           \
+               current->thread.wchan = 0;                      \
+       } while (0)
+
+#endif /* _ASM_C6X_SWITCH_TO_H */
diff --git a/arch/c6x/include/asm/system.h b/arch/c6x/include/asm/system.h
deleted file mode 100644 (file)
index e076dc0..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
- *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
- *
- *  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.
- */
-#ifndef _ASM_C6X_SYSTEM_H
-#define _ASM_C6X_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-#define prepare_to_switch()    do { } while (0)
-
-struct task_struct;
-struct thread_struct;
-asmlinkage void *__switch_to(struct thread_struct *prev,
-                            struct thread_struct *next,
-                            struct task_struct *tsk);
-
-#define switch_to(prev, next, last)                            \
-       do {                                                    \
-               current->thread.wchan = (u_long) __builtin_return_address(0); \
-               (last) = __switch_to(&(prev)->thread,           \
-                                    &(next)->thread, (prev));  \
-               mb();                                           \
-               current->thread.wchan = 0;                      \
-       } while (0)
-
-/* Reset the board */
-#define HARD_RESET_NOW()
-
-#define get_creg(reg) \
-       ({ unsigned int __x; \
-          asm volatile ("mvc .s2 " #reg ",%0\n" : "=b"(__x)); __x; })
-
-#define set_creg(reg, v) \
-       do { unsigned int __x = (unsigned int)(v); \
-               asm volatile ("mvc .s2 %0," #reg "\n" : : "b"(__x)); \
-       } while (0)
-
-#define or_creg(reg, n) \
-       do { unsigned __x, __n = (unsigned)(n);           \
-               asm volatile ("mvc .s2 " #reg ",%0\n"     \
-                             "or  .l2 %1,%0,%0\n"        \
-                             "mvc .s2 %0," #reg "\n"     \
-                             "nop\n"                     \
-                             : "=&b"(__x) : "b"(__n));   \
-       } while (0)
-
-#define and_creg(reg, n) \
-       do { unsigned __x, __n = (unsigned)(n);           \
-               asm volatile ("mvc .s2 " #reg ",%0\n"     \
-                             "and .l2 %1,%0,%0\n"        \
-                             "mvc .s2 %0," #reg "\n"     \
-                             "nop\n"    \
-                             : "=&b"(__x) : "b"(__n));   \
-       } while (0)
-
-#define get_coreid() (get_creg(DNUM) & 0xff)
-
-/* Set/get IST */
-#define set_ist(x)     set_creg(ISTP, x)
-#define get_ist()       get_creg(ISTP)
-
-/*
- * Exception management
- */
-asmlinkage void enable_exception(void);
-#define disable_exception()
-#define get_except_type()        get_creg(EFR)
-#define ack_exception(type)      set_creg(ECR, 1 << (type))
-#define get_iexcept()            get_creg(IERR)
-#define set_iexcept(mask)        set_creg(IERR, (mask))
-
-/*
- * Misc. functions
- */
-#define nop()                    asm("NOP\n");
-#define mb()                     barrier()
-#define rmb()                    barrier()
-#define wmb()                    barrier()
-#define set_mb(var, value)       do { var = value;  mb(); } while (0)
-#define set_wmb(var, value)      do { var = value; wmb(); } while (0)
-
-#define smp_mb()                barrier()
-#define smp_rmb()               barrier()
-#define smp_wmb()               barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned int)(x), (void *) (ptr), \
-                                   sizeof(*(ptr))))
-#define tas(ptr)    xchg((ptr), 1)
-
-unsigned int _lmbd(unsigned int, unsigned int);
-unsigned int _bitr(unsigned int);
-
-struct __xchg_dummy { unsigned int a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-static inline unsigned int __xchg(unsigned int x, volatile void *ptr, int size)
-{
-       unsigned int tmp;
-       unsigned long flags;
-
-       local_irq_save(flags);
-
-       switch (size) {
-       case 1:
-               tmp = 0;
-               tmp = *((unsigned char *) ptr);
-               *((unsigned char *) ptr) = (unsigned char) x;
-               break;
-       case 2:
-               tmp = 0;
-               tmp = *((unsigned short *) ptr);
-               *((unsigned short *) ptr) = x;
-               break;
-       case 4:
-               tmp = 0;
-               tmp = *((unsigned int *) ptr);
-               *((unsigned int *) ptr) = x;
-               break;
-       }
-       local_irq_restore(flags);
-       return tmp;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),             \
-                                                    (unsigned long)(o), \
-                                                    (unsigned long)(n), \
-                                                    sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#include <asm-generic/cmpxchg.h>
-
-#define _extu(x, s, e)                                                 \
-       ({      unsigned int __x;                                       \
-               asm volatile ("extu .S2 %3,%1,%2,%0\n" :                \
-                             "=b"(__x) : "n"(s), "n"(e), "b"(x));      \
-              __x; })
-
-
-extern unsigned int c6x_core_freq;
-
-struct pt_regs;
-
-extern void die(char *str, struct pt_regs *fp, int nr);
-extern asmlinkage int process_exception(struct pt_regs *regs);
-extern void time_init(void);
-extern void free_initmem(void);
-
-extern void (*c6x_restart)(void);
-extern void (*c6x_halt)(void);
-
-#endif /* _ASM_C6X_SYSTEM_H */
index d77bcfdf0d8e530ec6d87041f849c7c3afc16e2b..65b8ddf54b446ca904780dbc02a2e181fde037b1 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kernel_stat.h>
 
 #include <asm/megamod-pic.h>
+#include <asm/special_insns.h>
 
 unsigned long irq_err_count;
 
index 0c07921747f4d209f2ab7c978f14036d03308c57..ce46186600c51841a8d2ca9fb5d0b66cdf1e1976 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/dscr.h>
 #include <asm/clock.h>
 #include <asm/soc.h>
+#include <asm/special_insns.h>
 
 static const char *c6x_soc_name;
 
index dd45bc39af0e300fe30a416facbf334762d3b8c7..0748c94ebef6f9e1ba184047fc318561ade20121 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/etherdevice.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/soc.h>
 
index 4c9f136165f7c523ff93d14a760405ff0fb9694a..356ee84cad95aef68e6e9aca6f88b42e0eb931ec 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/timex.h>
 #include <linux/profile.h>
 
+#include <asm/special_insns.h>
 #include <asm/timer64.h>
 
 static u32 sched_clock_multiplier;
index f50e3edd6dadc384938fec5938681aabe5692268..1be74e5b47885015b908fa4954d1113a9651d2cc 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/bug.h>
 
 #include <asm/soc.h>
+#include <asm/special_insns.h>
 #include <asm/traps.h>
 
 int (*c6x_nmi_handler)(struct pt_regs *regs);
index 03c03c2491912084762027a2e5fecf9cbd6f7236..3c73d74a46742a5244a01ac320ac633bad769f50 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_address.h>
 #include <asm/soc.h>
 #include <asm/dscr.h>
+#include <asm/special_insns.h>
 #include <asm/timer64.h>
 
 struct timer_regs {
index 3d655dcc65da89df480c51d25c6b0b7199965053..74f99c688c8d9f800f67405a2bc291c699223283 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/capability.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <arch/svinto.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
index a276f0811731c8d0b3bb68f30c1bb3173a1c5e75..609d5510410e06e869567268a20edf133c588853 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/etraxgpio.h>
 #include <arch/svinto.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <arch/io_interface_mux.h>
 
index c413539d4205f929c75382bac787d74893575924..b3d1f9ed1b9881730b3583bb03df58f2acc08229 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/etraxi2c.h>
 
-#include <asm/system.h>
 #include <arch/svinto.h>
 #include <asm/io.h>
 #include <asm/delay.h>
index 1391b731ad1c5579b5317098bfc0c381270f34bb..9da056860c92426d8bf4ff905d1d88651c24602c 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
 
index 466af40c5822cfb93a8d0a14e007b513c8cc6e6c..c4b71710fb0ee504bd15fd6748cbfb9b8e249e1b 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 #include <arch/svinto.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/sync_serial.h>
 #include <arch/io_interface_mux.h>
 
index 99851ba8e5fa317cd0b2e8f8510e549683e30ebd..f932c85fbde48403f11b9056994411d1d50cbccc 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
-#include <asm/system.h>
 #include <arch/svinto.h>
 #include <asm/io.h>             /* Get SIMCOUT. */
 
index d31504b4a19e184360fe1916d8a14e670b354557..5795047359b2e825ac61dab09516521c159cb8d6 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <asm/dma.h>
 #include <arch/svinto.h>
+#include <arch/system.h>
 
 /* Macro to access ETRAX 100 registers */
 #define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
index 29f97e9627959f51e5e5354aaddde4936fd92d63..ad64cd1c861aa81d97d69bd4fa205c4fc2234d1b 100644 (file)
@@ -14,6 +14,7 @@
 #include <arch/svinto.h>
 #include <asm/io.h>
 #include <arch/io_interface_mux.h>
+#include <arch/system.h>
 
 
 #define DBG(s)
index 9a57db6907f5bb81762c6cc97b543284b289e703..bee8df43c201848e6c20439b88811efae05dfdd8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <arch/svinto.h>
 #include <linux/init.h>
+#include <arch/system.h>
 
 #ifdef CONFIG_ETRAX_GPIO
 void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */
index 320065f3cbe5d63ededd695fc2a23412cf033a07..bfddfb99401f96845761627016c0cf4be037bec6 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 
 /* 
index de27b50b72a24fb678865d5b58a7f7d426650ad6..4f96d71b51547f4ec656d0d587af0d88d0dd75f8 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/param.h>
+#include <arch/system.h>
 
 #ifdef CONFIG_PROC_FS
 #define HAS_FPU                0x0001
index e78fe49a98490723c16d7d3e9684e536dae4ec2a..289c584ba499505705bb1c8fce122609ac3f1cc0 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/processor.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
+#include <arch/system.h>
 
 #define DEBUG_SIG 0
 
index 8bebb96bbca1ba60eb09ecaa737462e0a1c9ff19..7001beda716c2c86077df3dc224d470244152965 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/ptrace.h>
 #include <asm/uaccess.h>
 #include <arch/sv_addr_ag.h>
+#include <arch/system.h>
 
 void
 show_registers(struct pt_regs *regs)
index ddb23996f11a8ef56183c155b82c20bd17214b48..3b2c82ce8147061f459bc4dd2c475f309e31e96c 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <asm/etraxi2c.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/delay.h>
 
index c845831e222590c7e6289d4fef846ea21305aadf..0b86deedacb97b9a0e919b79d484a35f43b456cc 100644 (file)
@@ -31,7 +31,6 @@
 #include <hwregs/gio_defs.h>
 #include <hwregs/intr_vect_defs.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/pinmux.h>
 
index ee90d2659be76db461cd12043bffe842160420a9..a2ac0917f1a615989243bd3c1d0dc091c7f2d552 100644 (file)
@@ -30,7 +30,6 @@
 #include <hwregs/gio_defs.h>
 #include <hwregs/intr_vect_defs.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
index 794b364d9f7d6e9d53af8f7d6857454351f8ca57..610909b003f61eb9b5f1ba0c33946cb3886283df 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/console.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <hwregs/reg_rdwr.h>
 #include <hwregs/reg_map.h>
 #include <hwregs/ser_defs.h>
index 111caa1a2efb4105aa0e45ae8552c8de6e5497a1..ab1551ee43c53c9c9c7aedbfe2e9d85a09600a1d 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <hwregs/reg_map.h>
 #include <hwregs/reg_rdwr.h>
index 511ece94a574a7b6ae2538774923e3d8e760140f..f7ad9e8637df271a1f9361ebede99b7f78966da0 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <arch/hwregs/supp_reg.h>
 
index f35e4f65f4efa8b0390d34e9f414246802793da0..47c64bf40eaee9371d022456be8db18dc6761660 100644 (file)
@@ -9,7 +9,6 @@
 #include <hwregs/clkgen_defs.h>
 #include <hwregs/strmux_defs.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <arbiter.h>
 
 static char used_dma_channels[MAX_DMA_CHANNELS];
index 2d970d7505c9c10d624103e3ab32d2f8493650e7..fc6416a671ea62e9e5a1d75bb452f417537d5e55 100644 (file)
@@ -9,7 +9,6 @@
 #include <hwregs/config_defs.h>
 #include <hwregs/strmux_defs.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <mach/arbiter.h>
 
 static char used_dma_channels[MAX_DMA_CHANNELS];
index 1c38ee728b1784930dc2d2a8ebb01e40139609d1..1eb638aeddb44446ce3b00a905905dc48ed53772 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASMCRIS_ARCH_ELF_H
 #define __ASMCRIS_ARCH_ELF_H
 
+#include <arch/system.h>
+
 #define ELF_MACH EF_CRIS_VARIANT_ANY_V0_V10
 
 /*
index 1324e505a4d84b1259011a92989912f64f4c03e8..c46d582911668faea3450d0009a635e17025f787 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_CRIS_ELF_H
 #define _ASM_CRIS_ELF_H
 
+#include <arch/system.h>
+
 #define ELF_CORE_EFLAGS EF_CRIS_VARIANT_V32
 
 /*
index 76cea99eaa6012a5e7f6335cf215e74dd1fc860c..db853fb3a45803bb1c875bd956274f272625aadf 100644 (file)
@@ -34,14 +34,4 @@ static inline unsigned long rdsp(void)
 /* Write the user-mode stack pointer. */
 #define wrusp(usp) __asm__ __volatile__ ("move %0, $usp" : : "rm" (usp))
 
-#define nop() __asm__ __volatile__ ("nop");
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long) (x),(ptr),sizeof(*(ptr))))
-
-#define tas(ptr) (xchg((ptr),1))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
 #endif /* _ASM_CRIS_ARCH_SYSTEM_H */
index bbf093814db2ac4054d1e165a12c06ab17e2f3a3..1056a5dfe04f3154f787155ac2f21b5f624d2c3b 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 #include <arch/atomic.h>
 
 /*
diff --git a/arch/cris/include/asm/barrier.h b/arch/cris/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..198ad7f
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ASM_CRIS_BARRIER_H
+#define __ASM_CRIS_BARRIER_H
+
+#define nop() __asm__ __volatile__ ("nop");
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+#define mb() barrier()
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()        mb()
+#define smp_rmb()       rmb()
+#define smp_wmb()       wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()        barrier()
+#define smp_rmb()       barrier()
+#define smp_wmb()       barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#endif /* __ASM_CRIS_BARRIER_H */
index a78a2d70cd8b2aa1acd2050a9006f88a9bfab163..184066ceb1f6146c9254a778c8e9c7f6b9656668 100644 (file)
@@ -19,7 +19,6 @@
 #endif
 
 #include <arch/bitops.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <linux/compiler.h>
 
diff --git a/arch/cris/include/asm/cmpxchg.h b/arch/cris/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..b756dac
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __ASM_CRIS_CMPXCHG__
+#define __ASM_CRIS_CMPXCHG__
+
+#include <linux/irqflags.h>
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+  /* since Etrax doesn't have any atomic xchg instructions, we need to disable
+     irq's (if enabled) and do it with move.d's */
+  unsigned long flags,temp;
+  local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
+  switch (size) {
+  case 1:
+    *((unsigned char *)&temp) = x;
+    x = *(unsigned char *)ptr;
+    *(unsigned char *)ptr = *((unsigned char *)&temp);
+    break;
+  case 2:
+    *((unsigned short *)&temp) = x;
+    x = *(unsigned short *)ptr;
+    *(unsigned short *)ptr = *((unsigned short *)&temp);
+    break;
+  case 4:
+    temp = x;
+    x = *(unsigned long *)ptr;
+    *(unsigned long *)ptr = temp;
+    break;
+  }
+  local_irq_restore(flags); /* restore irq enable bit */
+  return x;
+}
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#define tas(ptr) (xchg((ptr),1))
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#endif /* __ASM_CRIS_CMPXCHG__ */
diff --git a/arch/cris/include/asm/exec.h b/arch/cris/include/asm/exec.h
new file mode 100644 (file)
index 0000000..9665dab
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_CRIS_EXEC_H
+#define __ASM_CRIS_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_CRIS_EXEC_H */
index ce3fb25a460b81ef5e32592bd2c004afe4f9cbc9..72b3cd6eda0b4a09e69b51f9fd338874061c0c9e 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short  __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
 typedef __SIZE_TYPE__  __kernel_size_t;
 typedef long           __kernel_ssize_t;
 typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long            __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short  __kernel_uid16_t;
-typedef unsigned short  __kernel_gid16_t;
-typedef unsigned int    __kernel_uid32_t;
-typedef unsigned int    __kernel_gid32_t;
+#define __kernel_size_t __kernel_size_t
 
-typedef unsigned short  __kernel_old_uid_t;
-typedef unsigned short  __kernel_old_gid_t;
 typedef unsigned short __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#ifdef __KERNEL__
-
-#undef __FD_SET
-#define __FD_SET(fd,fdsetp) set_bit(fd, (void *)(fdsetp))
-
-#undef __FD_CLR
-#define __FD_CLR(fd,fdsetp) clear_bit(fd, (void *)(fdsetp))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd,fdsetp) test_bit(fd, (void *)(fdsetp))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) memset((void *)(fdsetp), 0, __FDSET_LONGS << 2)
-
-#endif /* __KERNEL__ */
+#define __kernel_old_dev_t __kernel_old_dev_t
 
 #endif /* __ARCH_CRIS_POSIX_TYPES_H */
index 3f7248f7a1c92357cb0f7158ad8e1965d6ed33e5..4210d72a6667417075e3c7f9e31674aefb8e1d9e 100644 (file)
 #ifndef __ASM_CRIS_PROCESSOR_H
 #define __ASM_CRIS_PROCESSOR_H
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <arch/processor.h>
+#include <arch/system.h>
 
 struct task_struct;
 
@@ -72,4 +72,13 @@ static inline void release_thread(struct task_struct *dead_task)
 
 #define cpu_relax()     barrier()
 
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
+void default_idle(void);
+
 #endif /* __ASM_CRIS_PROCESSOR_H */
diff --git a/arch/cris/include/asm/switch_to.h b/arch/cris/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..d842e11
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ASM_CRIS_SWITCH_TO_H
+#define __ASM_CRIS_SWITCH_TO_H
+
+/* the switch_to macro calls resume, an asm function in entry.S which does the actual
+ * task switching.
+ */
+
+extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
+#define switch_to(prev,next,last) last = resume(prev,next, \
+                                        (int)&((struct task_struct *)0)->thread)
+
+#endif /* __ASM_CRIS_SWITCH_TO_H */
diff --git a/arch/cris/include/asm/system.h b/arch/cris/include/asm/system.h
deleted file mode 100644 (file)
index ea10592..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef __ASM_CRIS_SYSTEM_H
-#define __ASM_CRIS_SYSTEM_H
-
-#include <linux/irqflags.h>
-#include <arch/system.h>
-
-/* the switch_to macro calls resume, an asm function in entry.S which does the actual
- * task switching.
- */
-
-extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
-#define switch_to(prev,next,last) last = resume(prev,next, \
-                                        (int)&((struct task_struct *)0)->thread)
-
-#define barrier() __asm__ __volatile__("": : :"memory")
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()        mb()
-#define smp_rmb()       rmb()
-#define smp_wmb()       wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()        barrier()
-#define smp_rmb()       barrier()
-#define smp_wmb()       barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#define iret()
-
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-void disable_hlt(void);
-void enable_hlt(void);
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  /* since Etrax doesn't have any atomic xchg instructions, we need to disable
-     irq's (if enabled) and do it with move.d's */
-  unsigned long flags,temp;
-  local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
-  switch (size) {
-  case 1:
-    *((unsigned char *)&temp) = x;
-    x = *(unsigned char *)ptr;
-    *(unsigned char *)ptr = *((unsigned char *)&temp);
-    break;
-  case 2:
-    *((unsigned short *)&temp) = x;
-    x = *(unsigned short *)ptr;
-    *(unsigned short *)ptr = *((unsigned short *)&temp);
-    break;
-  case 4:
-    temp = x;
-    x = *(unsigned long *)ptr;
-    *(unsigned long *)ptr = temp;
-    break;
-  }
-  local_irq_restore(flags); /* restore irq enable bit */
-  return x;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define arch_align_stack(x) (x)
-
-void default_idle(void);
-
-#endif
index 788eb2248916785d0f0afda6d8b23dda2f3c250f..d36836dbbc0722758f9e116537c5e413a6e4871a 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
+#include <arch/system.h>
 
 /* called by the assembler IRQ entry functions defined in irq.h
  * to dispatch the interrupts to registered handlers
index d8f50ff6fadd07058925d80af879d322599a5f6d..891dad85e8bd4fae33233f5abb71c453b3ade5c2 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/init_task.h>
index 48b0f3912632f98d48ae22e40945d057aa393269..d114ad3da9b15f95ccc5a68b736d5e80bae75af7 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 
 
index b712f4934c4bb1ef8503ce3d3af4c405f1443e06..32c3d248868e27c152932c7e9baf98410a1b3128 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pfn.h>
 #include <linux/cpu.h>
 #include <asm/setup.h>
+#include <arch/system.h>
 
 /*
  * Setup options
index 8da53f34c7a72ffb509834f89d905b16a2575016..a11ad3229f8c4dc50474ed0af99a1cbcb4d1f21b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <arch/system.h>
 
 extern void arch_enable_nmi(void);
 extern void stop_watchdog(void);
index 9dcac8ec8fa0b8837f7faa9a08b31ccd5a256716..b4760d86e1bba7b8674b933eb66d798e5ce4d1c9 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
+#include <arch/system.h>
 
 extern int find_fixup_code(struct pt_regs *);
 extern void die_if_kernel(const char *, struct pt_regs *, long);
index 0d8a7d66174000e3ebfbd5193bed1ace42d79c96..b86329d0e31656775cb2c1a01c0f6665ea2c5b5a 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <linux/types.h>
 #include <asm/spr-regs.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #ifdef CONFIG_SMP
 #error not SMP safe
@@ -181,61 +181,6 @@ static inline void atomic64_dec(atomic64_t *v)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
 #define atomic64_inc_and_test(v)       (atomic64_inc_return((v)) == 0)
 
-/*****************************************************************************/
-/*
- * exchange value with memory
- */
-extern uint64_t __xchg_64(uint64_t i, volatile void *v);
-
-#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
-
-#define xchg(ptr, x)                                                           \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig;                                           \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4:                                                                 \
-               asm volatile(                                                   \
-                       "swap%I0 %M0,%1"                                        \
-                       : "+m"(*__xg_ptr), "=r"(__xg_orig)                      \
-                       : "1"(x)                                                \
-                       : "memory"                                              \
-                       );                                                      \
-               break;                                                          \
-                                                                               \
-       default:                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                           \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#else
-
-extern uint32_t __xchg_32(uint32_t i, volatile void *v);
-
-#define xchg(ptr, x)                                                                           \
-({                                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                                       \
-       __typeof__(*(ptr)) __xg_orig;                                                           \
-                                                                                               \
-       switch (sizeof(__xg_orig)) {                                                            \
-       case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr);     break;  \
-       default:                                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                                                                   \
-               asm volatile("break");                                                          \
-               break;                                                                          \
-       }                                                                                       \
-       __xg_orig;                                                                              \
-})
-
-#endif
-
-#define tas(ptr) (xchg((ptr), 1))
-
 #define atomic_cmpxchg(v, old, new)    (cmpxchg(&(v)->counter, old, new))
 #define atomic_xchg(v, new)            (xchg(&(v)->counter, new))
 #define atomic64_cmpxchg(v, old, new)  (__cmpxchg_64(old, new, &(v)->counter))
diff --git a/arch/frv/include/asm/barrier.h b/arch/frv/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..06776ad
--- /dev/null
@@ -0,0 +1,29 @@
+/* FR-V CPU memory barrier definitions
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_BARRIER_H
+#define _ASM_BARRIER_H
+
+#define nop()                  asm volatile ("nop"::)
+
+#define mb()                   asm volatile ("membar" : : :"memory")
+#define rmb()                  asm volatile ("membar" : : :"memory")
+#define wmb()                  asm volatile ("membar" : : :"memory")
+#define read_barrier_depends() do { } while (0)
+
+#define smp_mb()                       barrier()
+#define smp_rmb()                      barrier()
+#define smp_wmb()                      barrier()
+#define smp_read_barrier_depends()     do {} while(0)
+#define set_mb(var, value) \
+       do { var = (value); barrier(); } while (0)
+
+#endif /* _ASM_BARRIER_H */
index 2e054508a2f66714376ba0b5c5e880405c15be41..dd01bcf42ee6e56f8f698eefc2a464d08fa408d8 100644 (file)
@@ -51,4 +51,6 @@ do {                                          \
 
 #include <asm-generic/bug.h>
 
+extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
+
 #endif
diff --git a/arch/frv/include/asm/cmpxchg.h b/arch/frv/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..5b04dd0
--- /dev/null
@@ -0,0 +1,172 @@
+/* xchg and cmpxchg operation emulation for FR-V
+ *
+ * For an explanation of how atomic ops work in this arch, see:
+ *   Documentation/frv/atomic-ops.txt
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+#include <linux/types.h>
+
+/*****************************************************************************/
+/*
+ * exchange value with memory
+ */
+extern uint64_t __xchg_64(uint64_t i, volatile void *v);
+
+#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+
+#define xchg(ptr, x)                                                           \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig;                                           \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4:                                                                 \
+               asm volatile(                                                   \
+                       "swap%I0 %M0,%1"                                        \
+                       : "+m"(*__xg_ptr), "=r"(__xg_orig)                      \
+                       : "1"(x)                                                \
+                       : "memory"                                              \
+                       );                                                      \
+               break;                                                          \
+                                                                               \
+       default:                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                           \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#else
+
+extern uint32_t __xchg_32(uint32_t i, volatile void *v);
+
+#define xchg(ptr, x)                                                                           \
+({                                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                                       \
+       __typeof__(*(ptr)) __xg_orig;                                                           \
+                                                                                               \
+       switch (sizeof(__xg_orig)) {                                                            \
+       case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr);     break;  \
+       default:                                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                                                                   \
+               asm volatile("break");                                                          \
+               break;                                                                          \
+       }                                                                                       \
+       __xg_orig;                                                                              \
+})
+
+#endif
+
+#define tas(ptr) (xchg((ptr), 1))
+
+/*****************************************************************************/
+/*
+ * compare and conditionally exchange value with memory
+ * - if (*ptr == test) then orig = *ptr; *ptr = test;
+ * - if (*ptr != test) then orig = *ptr;
+ */
+extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v);
+
+#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+
+#define cmpxchg(ptr, test, new)                                                        \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
+       __typeof__(*(ptr)) __xg_test = (test);                                  \
+       __typeof__(*(ptr)) __xg_new = (new);                                    \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4:                                                                 \
+               asm volatile(                                                   \
+                       "0:                                             \n"     \
+                       "       orcc            gr0,gr0,gr0,icc3        \n"     \
+                       "       ckeq            icc3,cc7                \n"     \
+                       "       ld.p            %M0,%1                  \n"     \
+                       "       orcr            cc7,cc7,cc3             \n"     \
+                       "       sub%I4cc        %1,%4,%2,icc0           \n"     \
+                       "       bne             icc0,#0,1f              \n"     \
+                       "       cst.p           %3,%M0          ,cc3,#1 \n"     \
+                       "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
+                       "       beq             icc3,#0,0b              \n"     \
+                       "1:                                             \n"     \
+                       : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
+                       : "r"(__xg_new), "NPr"(__xg_test)                       \
+                       : "memory", "cc7", "cc3", "icc3", "icc0"                \
+                       );                                                      \
+               break;                                                          \
+                                                                               \
+       default:                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                           \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#else
+
+extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
+
+#define cmpxchg(ptr, test, new)                                                        \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig;                                           \
+       __typeof__(*(ptr)) __xg_test = (test);                                  \
+       __typeof__(*(ptr)) __xg_new = (new);                                    \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4: __xg_orig = (__force __typeof__(*ptr))                          \
+                       __cmpxchg_32((__force uint32_t *)__xg_ptr,              \
+                                        (__force uint32_t)__xg_test,           \
+                                        (__force uint32_t)__xg_new); break;    \
+       default:                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                           \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#endif
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return cmpxchg((unsigned long *)ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* _ASM_CMPXCHG_H */
diff --git a/arch/frv/include/asm/exec.h b/arch/frv/include/asm/exec.h
new file mode 100644 (file)
index 0000000..65c9130
--- /dev/null
@@ -0,0 +1,17 @@
+/* FR-V CPU executable handling
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_EXEC_H */
index a9f1f5be0632e86bdecdda60d3dccffdb6510e7a..3f34cb45fbb3fafd24edff901ca8b52d9941532d 100644 (file)
@@ -7,56 +7,23 @@
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
+#define __kernel_uid_t __kernel_uid_t
 
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef __FD_CLR
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef __FD_ISSET
-#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif
 
diff --git a/arch/frv/include/asm/switch_to.h b/arch/frv/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..2cf0f6a
--- /dev/null
@@ -0,0 +1,35 @@
+/* FR-V CPU basic task switching
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ * The `mb' is to tell GCC not to cache `current' across this call.
+ */
+extern asmlinkage
+struct task_struct *__switch_to(struct thread_struct *prev_thread,
+                               struct thread_struct *next_thread,
+                               struct task_struct *prev);
+
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       (prev)->thread.sched_lr =                                       \
+               (unsigned long) __builtin_return_address(0);            \
+       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
+       mb();                                                           \
+} while(0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/frv/include/asm/system.h b/arch/frv/include/asm/system.h
deleted file mode 100644 (file)
index 6c10fd2..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* system.h: FR-V CPU control definitions
- *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <linux/types.h>
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-
-struct thread_struct;
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.
- * The `mb' is to tell GCC not to cache `current' across this call.
- */
-extern asmlinkage
-struct task_struct *__switch_to(struct thread_struct *prev_thread,
-                               struct thread_struct *next_thread,
-                               struct task_struct *prev);
-
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       (prev)->thread.sched_lr =                                       \
-               (unsigned long) __builtin_return_address(0);            \
-       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
-       mb();                                                           \
-} while(0)
-
-/*
- * Force strict CPU ordering.
- */
-#define nop()                  asm volatile ("nop"::)
-#define mb()                   asm volatile ("membar" : : :"memory")
-#define rmb()                  asm volatile ("membar" : : :"memory")
-#define wmb()                  asm volatile ("membar" : : :"memory")
-#define read_barrier_depends() do { } while (0)
-
-#define smp_mb()                       barrier()
-#define smp_rmb()                      barrier()
-#define smp_wmb()                      barrier()
-#define smp_read_barrier_depends()     do {} while(0)
-#define set_mb(var, value) \
-       do { var = (value); barrier(); } while (0)
-
-extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
-extern void free_initmem(void);
-
-#define arch_align_stack(x) (x)
-
-/*****************************************************************************/
-/*
- * compare and conditionally exchange value with memory
- * - if (*ptr == test) then orig = *ptr; *ptr = test;
- * - if (*ptr != test) then orig = *ptr;
- */
-extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v);
-
-#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
-
-#define cmpxchg(ptr, test, new)                                                        \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
-       __typeof__(*(ptr)) __xg_test = (test);                                  \
-       __typeof__(*(ptr)) __xg_new = (new);                                    \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4:                                                                 \
-               asm volatile(                                                   \
-                       "0:                                             \n"     \
-                       "       orcc            gr0,gr0,gr0,icc3        \n"     \
-                       "       ckeq            icc3,cc7                \n"     \
-                       "       ld.p            %M0,%1                  \n"     \
-                       "       orcr            cc7,cc7,cc3             \n"     \
-                       "       sub%I4cc        %1,%4,%2,icc0           \n"     \
-                       "       bne             icc0,#0,1f              \n"     \
-                       "       cst.p           %3,%M0          ,cc3,#1 \n"     \
-                       "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
-                       "       beq             icc3,#0,0b              \n"     \
-                       "1:                                             \n"     \
-                       : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
-                       : "r"(__xg_new), "NPr"(__xg_test)                       \
-                       : "memory", "cc7", "cc3", "icc3", "icc0"                \
-                       );                                                      \
-               break;                                                          \
-                                                                               \
-       default:                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                           \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#else
-
-extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
-
-#define cmpxchg(ptr, test, new)                                                        \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig;                                           \
-       __typeof__(*(ptr)) __xg_test = (test);                                  \
-       __typeof__(*(ptr)) __xg_new = (new);                                    \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4: __xg_orig = (__force __typeof__(*ptr))                          \
-                       __cmpxchg_32((__force uint32_t *)__xg_ptr,              \
-                                        (__force uint32_t)__xg_test,           \
-                                        (__force uint32_t)__xg_new); break;    \
-       default:                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                           \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return cmpxchg((unsigned long *)ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif /* _ASM_SYSTEM_H */
index 2845139c8077d3208d8041c974eeb1bd2be844f4..a0228f717ef2be37abd55d91bcbbfd48c4429609 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/serial_reg.h>
 #include <linux/start_kernel.h>
 
-#include <asm/system.h>
 #include <asm/serial-regs.h>
 #include <asm/timer-regs.h>
 #include <asm/irc-regs.h>
index 2ca641d199f81b7eef23159bd82edf4ed1259ca3..0707d35079baefd1d3427f5af86ee1d7b98c2d5f 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/serial_reg.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/irc-regs.h>
 #include <asm/timer-regs.h>
 #include <asm/gdb-stub.h>
index a6d5381c94fee5cb871099bea62b9db848b3efaa..bbe78b0bffecdca56da891246525d09ca9717a1f 100644 (file)
 
 #include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 
 #define LEDS(x) do { /* *(u32*)0xe1200004 = ~(x); mb(); */ } while(0)
index 9afc2ea400dc4b79931c624d7013251706ae1a0e..2cc327a1ca44c51cbb455ddbf200532597c78131 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/irc-regs.h>
index 4d4ad09d3c919e7ff8cdcf38f79aecff42ecf210..95e4eb4f1f383adb5c5bf552552d64fb7175ad33 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/irc-regs.h>
index 4d034c7840c9270f26359cb32378cab20e321b18..ba648da0932daec3fc71da4feec67ac660a31e12 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/irc-regs.h>
index 3facbc28cbbcf2be4f72d6f16ac1d6dd5fd9562f..2239346fa3db6e8ad72aba63344e3d8b08120c53 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/delay.h>
index 29cc49783787224ac84961b1577e2e7b02b32c9f..d4de48bd5efe4211990ec7530e25ad95e97819ad 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <asm/asm-offsets.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
index 9d68f7fac73041c6902c1e98b90580a59fe0f82f..3987ff88dab0cd14d6273a05b86b6c8aef07d94a 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/unistd.h>
 
index 1d2dfe67d4426b7805e595f75293b5b46e5f6a8f..5cfd1420b09141dd0e270af0197dbf8e63836171 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/siginfo.h>
index a325d57a83d5fdae12d8323480564d8204e86117..331c1e2cfb6760ee7ed3f38d4e5c92a2526d44bf 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/gdb-stub.h>
index fbe5f0dbae06eb588d3d6be5106e5ffeeaebdf9b..a19effcccb34cbf1a60e0404e18a01758ba84d61 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/virtconvert.h>
 #include <asm/sections.h>
index fb78be38ea02633825f1ef904e9b1b5d6012a0b9..e9217e605aa85c47300dc17be7234291e477cf7a 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index f5a38c1f5489f8d5dda4a1fb2b0be5613867b6bb..40901e353c2181a9ef2c747b40bd64c4c7f0b8b2 100644 (file)
@@ -2,6 +2,7 @@
 #define __ARCH_H8300_ATOMIC__
 
 #include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -13,7 +14,6 @@
 #define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
-#include <asm/system.h>
 #include <linux/kernel.h>
 
 static __inline__ int atomic_add_return(int i, atomic_t *v)
@@ -102,8 +102,6 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
        return ret;
 }
 
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int ret;
diff --git a/arch/h8300/include/asm/barrier.h b/arch/h8300/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..c7283c3
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _H8300_BARRIER_H
+#define _H8300_BARRIER_H
+
+#define nop()  asm volatile ("nop"::)
+
+/*
+ * Force strict CPU ordering.
+ * Not really required on H8...
+ */
+#define mb()   asm volatile (""   : : :"memory")
+#define rmb()  asm volatile (""   : : :"memory")
+#define wmb()  asm volatile (""   : : :"memory")
+#define set_mb(var, value) do { xchg(&var, value); } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#endif /* _H8300_BARRIER_H */
index e856c1bb34157e36ad433400b1d10945e0c056e0..eb34e0cd33d5c9c7ebbd8b010975dad1486c97ca 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/compiler.h>
-#include <asm/system.h>
 
 #ifdef __KERNEL__
 
index 887c19773185d2da7442fb81b5090a0742de571b..1e1be8119935b5e47bd2818883fbdd926e415274 100644 (file)
@@ -5,4 +5,8 @@
 #define is_valid_bugaddr(addr) (1)
 
 #include <asm-generic/bug.h>
+
+struct pt_regs;
+extern void die(const char *str, struct pt_regs *fp, unsigned long err);
+
 #endif
diff --git a/arch/h8300/include/asm/cmpxchg.h b/arch/h8300/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..cdb203e
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __ARCH_H8300_CMPXCHG__
+#define __ARCH_H8300_CMPXCHG__
+
+#include <linux/irqflags.h>
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+  unsigned long tmp, flags;
+
+  local_irq_save(flags);
+
+  switch (size) {
+  case 1:
+    __asm__ __volatile__
+    ("mov.b %2,%0\n\t"
+     "mov.b %1,%2"
+    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
+    break;
+  case 2:
+    __asm__ __volatile__
+    ("mov.w %2,%0\n\t"
+     "mov.w %1,%2"
+    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
+    break;
+  case 4:
+    __asm__ __volatile__
+    ("mov.l %2,%0\n\t"
+     "mov.l %1,%2"
+    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
+    break;
+  default:
+    tmp = 0;     
+  }
+  local_irq_restore(flags);
+  return tmp;
+}
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#endif /* __ARCH_H8300_CMPXCHG__ */
diff --git a/arch/h8300/include/asm/exec.h b/arch/h8300/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c01c45c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _H8300_EXEC_H
+#define _H8300_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _H8300_EXEC_H */
index 6f833a16f694ca36383b5216b726966b35633766..bc4c34efb1ad167ccafa90ee8796d605058572a0 100644 (file)
@@ -7,54 +7,23 @@
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
+#define __kernel_uid_t __kernel_uid_t
 
 typedef unsigned short __kernel_old_uid_t;
 typedef unsigned short __kernel_old_gid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
 
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef __FD_CLR
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef __FD_ISSET
-#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif
index e834b60188977b0a047df1d95d4e29e2cf9b36b1..61fabf1788c6b4e1a9c006d29a070b2b1bfb5904 100644 (file)
@@ -135,4 +135,9 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()    barrier()
 
+#define HARD_RESET_NOW() ({            \
+        local_irq_disable();           \
+        asm("jmp @@0");                        \
+})
+
 #endif
diff --git a/arch/h8300/include/asm/switch_to.h b/arch/h8300/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..cdd8731
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _H8300_SWITCH_TO_H
+#define _H8300_SWITCH_TO_H
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.  This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+/*
+ * switch_to() saves the extra registers, that are not saved
+ * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
+ * a0-a1. Some of these are used by schedule() and its predecessors
+ * and so we might get see unexpected behaviors when a task returns
+ * with unexpected register values.
+ *
+ * syscall stores these registers itself and none of them are used
+ * by syscall after the function in the syscall has been called.
+ *
+ * Beware that resume now expects *next to be in d1 and the offset of
+ * tss to be in a1. This saves a few instructions as we no longer have
+ * to push them onto the stack and read them back right after.
+ *
+ * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
+ *
+ * Changed 96/09/19 by Andreas Schwab
+ * pass prev in a0, next in a1, offset of tss in d1, and whether
+ * the mm structures are shared in d2 (to avoid atc flushing).
+ *
+ * H8/300 Porting 2002/09/04 Yoshinori Sato
+ */
+
+asmlinkage void resume(void);
+#define switch_to(prev,next,last) {                         \
+  void *_last;                                             \
+  __asm__ __volatile__(                                            \
+                       "mov.l  %1, er0\n\t"                \
+                       "mov.l  %2, er1\n\t"                \
+                        "mov.l  %3, er2\n\t"                \
+                       "jsr @_resume\n\t"                  \
+                        "mov.l  er2,%0\n\t"                 \
+                      : "=r" (_last)                       \
+                      : "r" (&(prev->thread)),             \
+                        "r" (&(next->thread)),             \
+                         "g" (prev)                         \
+                      : "cc", "er0", "er1", "er2", "er3"); \
+  (last) = _last;                                          \
+}
+
+#endif /* _H8300_SWITCH_TO_H */
diff --git a/arch/h8300/include/asm/system.h b/arch/h8300/include/asm/system.h
deleted file mode 100644 (file)
index 2c2382e..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _H8300_SYSTEM_H
-#define _H8300_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-struct pt_regs;
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1, offset of tss in d1, and whether
- * the mm structures are shared in d2 (to avoid atc flushing).
- *
- * H8/300 Porting 2002/09/04 Yoshinori Sato
- */
-
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) {                         \
-  void *_last;                                             \
-  __asm__ __volatile__(                                            \
-                       "mov.l  %1, er0\n\t"                \
-                       "mov.l  %2, er1\n\t"                \
-                        "mov.l  %3, er2\n\t"                \
-                       "jsr @_resume\n\t"                  \
-                        "mov.l  er2,%0\n\t"                 \
-                      : "=r" (_last)                       \
-                      : "r" (&(prev->thread)),             \
-                        "r" (&(next->thread)),             \
-                         "g" (prev)                         \
-                      : "cc", "er0", "er1", "er2", "er3"); \
-  (last) = _last;                                          \
-}
-
-#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
-
-/*
- * Force strict CPU ordering.
- * Not really required on H8...
- */
-#define nop()  asm volatile ("nop"::)
-#define mb()   asm volatile (""   : : :"memory")
-#define rmb()  asm volatile (""   : : :"memory")
-#define wmb()  asm volatile (""   : : :"memory")
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  unsigned long tmp, flags;
-
-  local_irq_save(flags);
-
-  switch (size) {
-  case 1:
-    __asm__ __volatile__
-    ("mov.b %2,%0\n\t"
-     "mov.b %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 2:
-    __asm__ __volatile__
-    ("mov.w %2,%0\n\t"
-     "mov.w %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 4:
-    __asm__ __volatile__
-    ("mov.l %2,%0\n\t"
-     "mov.l %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  default:
-    tmp = 0;     
-  }
-  local_irq_restore(flags);
-  return tmp;
-}
-
-#define HARD_RESET_NOW() ({            \
-        local_irq_disable();           \
-        asm("jmp @@0");                        \
-})
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define arch_align_stack(x) (x)
-
-extern void die(const char *str, struct pt_regs *fp, unsigned long err);
-
-#endif /* _H8300_SYSTEM_H */
index 1f67fed476afdead1be58fe924aace28cd89b558..2fa8ac7b79b5af5a91e156f58b3e7a1467ddc4d2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/setup.h>
index 1a173b35f47556c6448a40a1fc70a5ba4b5b748e..0e9c315be1040cdc85284384596a5da02984b3eb 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
index 497fa89b5df40815ca3b20b4c252a8d9e09c3d1a..748cf6585aa4369ec6b16d540493ccc84138001f 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/signal.h>
 
index dfa05bd908b6b22139c388ebbe983721c39b6100..7833aa3e7c7dd2b845de79f1c7b7201a5521ea09 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 #include <linux/bug.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/page.h>
index 1d092abebf03bcfbeabfbe41f67b99cb1260e58e..472535977006b6405bed220f658c0aae9d32f5b0 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 
 /*
index 7cc3380f250cc608ea8815472a5652d2b1b04c3b..973369c32a957cd4a1780e922301268ae0c30e19 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index 944a502c2e561a53905151eb18c0b70d90aab110..f79edcdadf39b5207d5b3150e9dcb0d950f7f73f 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index 5552ddfaab5ea69c5417f955eb32aa7ddb043c70..06e364641392560b6c31622d7cdf053c0d582b50 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 
index e220f90530358bcfb5a11450c2e904b2f3733683..3e258043337b322a44322bfda4b2eb1f70595df5 100644 (file)
@@ -23,6 +23,7 @@
 #define _ASM_ATOMIC_H
 
 #include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 #define atomic_set(v, i)       ((v)->counter = (i))
diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..a4ed6e2
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Memory barrier definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BARRIER_H
+#define _ASM_BARRIER_H
+
+#define rmb()                          barrier()
+#define read_barrier_depends()         barrier()
+#define wmb()                          barrier()
+#define mb()                           barrier()
+#define smp_rmb()                      barrier()
+#define smp_read_barrier_depends()     barrier()
+#define smp_wmb()                      barrier()
+#define smp_mb()                       barrier()
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
+/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
+#define set_mb(var, value) \
+       do { var = value; mb(); } while (0)
+
+#endif /* _ASM_BARRIER_H */
index d23461e080ffa65abd64f81de09fc3bad2568746..4caa649ad78b06551120f7be0749e2e986892132 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/compiler.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/atomic.h>
 
 #ifdef __KERNEL__
diff --git a/arch/hexagon/include/asm/cmpxchg.h b/arch/hexagon/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..c5f9527
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * xchg/cmpxchg operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+/*
+ * __xchg - atomically exchange a register and a memory location
+ * @x: value to swap
+ * @ptr: pointer to memory
+ * @size:  size of the value
+ *
+ * Only 4 bytes supported currently.
+ *
+ * Note:  there was an errata for V2 about .new's and memw_locked.
+ *
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                  int size)
+{
+       unsigned long retval;
+
+       /*  Can't seem to use printk or panic here, so just stop  */
+       if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
+
+       __asm__ __volatile__ (
+       "1:     %0 = memw_locked(%1);\n"    /*  load into retval */
+       "       memw_locked(%1,P0) = %2;\n" /*  store into memory */
+       "       if !P0 jump 1b;\n"
+       : "=&r" (retval)
+       : "r" (ptr), "r" (x)
+       : "memory", "p0"
+       );
+       return retval;
+}
+
+/*
+ * Atomically swap the contents of a register with memory.  Should be atomic
+ * between multiple CPU's and within interrupts on the same CPU.
+ */
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+       sizeof(*(ptr))))
+
+/*
+ *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
+ *  looks just like atomic_cmpxchg on our arch currently with a bunch of
+ *  variable casting.
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define cmpxchg(ptr, old, new)                                 \
+({                                                             \
+       __typeof__(ptr) __ptr = (ptr);                          \
+       __typeof__(*(ptr)) __old = (old);                       \
+       __typeof__(*(ptr)) __new = (new);                       \
+       __typeof__(*(ptr)) __oldval = 0;                        \
+                                                               \
+       asm volatile(                                           \
+               "1:     %0 = memw_locked(%1);\n"                \
+               "       { P0 = cmp.eq(%0,%2);\n"                \
+               "         if (!P0.new) jump:nt 2f; }\n"         \
+               "       memw_locked(%1,p0) = %3;\n"             \
+               "       if (!P0) jump 1b;\n"                    \
+               "2:\n"                                          \
+               : "=&r" (__oldval)                              \
+               : "r" (__ptr), "r" (__old), "r" (__new)         \
+               : "memory", "p0"                                \
+       );                                                      \
+       __oldval;                                               \
+})
+
+#endif /* _ASM_CMPXCHG_H */
diff --git a/arch/hexagon/include/asm/exec.h b/arch/hexagon/include/asm/exec.h
new file mode 100644 (file)
index 0000000..350e6d4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Process execution related definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+/*  Should probably shoot for an 8-byte aligned stack pointer  */
+#define STACK_MASK (~7)
+#define arch_align_stack(x) (x & STACK_MASK)
+
+#endif /* _ASM_EXEC_H */
diff --git a/arch/hexagon/include/asm/switch_to.h b/arch/hexagon/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..28ca0df
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Task switching definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+struct thread_struct;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+       struct task_struct *,
+       struct task_struct *);
+
+#define switch_to(p, n, r) do {\
+       r = __switch_to((p), (n), (r));\
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/hexagon/include/asm/system.h b/arch/hexagon/include/asm/system.h
deleted file mode 100644 (file)
index 323ed1d..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * System level definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-#include <asm/atomic.h>
-#include <asm/hexagon_vm.h>
-
-struct thread_struct;
-
-extern struct task_struct *__switch_to(struct task_struct *,
-       struct task_struct *,
-       struct task_struct *);
-
-#define switch_to(p, n, r) do {\
-       r = __switch_to((p), (n), (r));\
-} while (0)
-
-
-#define rmb()                          barrier()
-#define read_barrier_depends()         barrier()
-#define wmb()                          barrier()
-#define mb()                           barrier()
-#define smp_rmb()                      barrier()
-#define smp_read_barrier_depends()     barrier()
-#define smp_wmb()                      barrier()
-#define smp_mb()                       barrier()
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec()     barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc()     barrier()
-
-/*
- * __xchg - atomically exchange a register and a memory location
- * @x: value to swap
- * @ptr: pointer to memory
- * @size:  size of the value
- *
- * Only 4 bytes supported currently.
- *
- * Note:  there was an errata for V2 about .new's and memw_locked.
- *
- */
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
-                                  int size)
-{
-       unsigned long retval;
-
-       /*  Can't seem to use printk or panic here, so just stop  */
-       if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
-
-       __asm__ __volatile__ (
-       "1:     %0 = memw_locked(%1);\n"    /*  load into retval */
-       "       memw_locked(%1,P0) = %2;\n" /*  store into memory */
-       "       if !P0 jump 1b;\n"
-       : "=&r" (retval)
-       : "r" (ptr), "r" (x)
-       : "memory", "p0"
-       );
-       return retval;
-}
-
-/*
- * Atomically swap the contents of a register with memory.  Should be atomic
- * between multiple CPU's and within interrupts on the same CPU.
- */
-#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
-       sizeof(*(ptr))))
-
-/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
-#define set_mb(var, value) \
-       do { var = value; mb(); } while (0)
-
-/*
- *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
- *  looks just like atomic_cmpxchg on our arch currently with a bunch of
- *  variable casting.
- */
-#define __HAVE_ARCH_CMPXCHG 1
-
-#define cmpxchg(ptr, old, new)                                 \
-({                                                             \
-       __typeof__(ptr) __ptr = (ptr);                          \
-       __typeof__(*(ptr)) __old = (old);                       \
-       __typeof__(*(ptr)) __new = (new);                       \
-       __typeof__(*(ptr)) __oldval = 0;                        \
-                                                               \
-       asm volatile(                                           \
-               "1:     %0 = memw_locked(%1);\n"                \
-               "       { P0 = cmp.eq(%0,%2);\n"                \
-               "         if (!P0.new) jump:nt 2f; }\n"         \
-               "       memw_locked(%1,p0) = %3;\n"             \
-               "       if (!P0) jump 1b;\n"                    \
-               "2:\n"                                          \
-               : "=&r" (__oldval)                              \
-               : "r" (__ptr), "r" (__old), "r" (__new)         \
-               : "memory", "p0"                                \
-       );                                                      \
-       __oldval;                                               \
-})
-
-/*  Should probably shoot for an 8-byte aligned stack pointer  */
-#define STACK_MASK (~7)
-#define arch_align_stack(x) (x & STACK_MASK)
-
-#endif
index bea3f08470fd226c7c5bf7024b906d1feb676468..32342de1a79c7ae6951fe819c56de0d53a3b999d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/regset.h>
 #include <linux/user.h>
 
-#include <asm/system.h>
 #include <asm/user.h>
 
 static int genregs_get(struct task_struct *target,
index 0123c63e9a3abe8b3b99eae8feb9609a566e850e..15d1fd22bbc54fba10da9b9caf9598619e7cd7ec 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/smp.h>
 #include <linux/spinlock.h>
 
-#include <asm/system.h>  /*  xchg  */
 #include <asm/time.h>    /*  timer_interrupt  */
 #include <asm/hexagon_vm.h>
 
index 986a081e32ec867ba31af43ee385e32146784753..591fc1b68635e00b86bb2ba73134d2e71d5c0125 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/registers.h>
 #include <linux/irq.h>
 #include <linux/hardirq.h>
-#include <asm/system.h>
 
 /*
  * show_regs - print pt_regs structure
index 9196b330ff7fa917c0508ca6e5b35578b0bffc86..98131e1db7a091cc53561cab79a388aa02ac15aa 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <asm/io.h>
 #include <asm/machvec.h>
-#include <asm/system.h>
+#include <asm/setup.h>
 
 void __init
 dig_setup (char **cmdline_p)
index f5f4ef149aacf35f3988ddc47379a13ee27bd371..f6ea3a3b4a842e8e0099d967f07a647786fff7d0 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/io.h>
 #include <asm/page.h>          /* PAGE_OFFSET */
 #include <asm/dma.h>
-#include <asm/system.h>                /* wmb() */
 
 #include <asm/acpi-ext.h>
 
index c5e9baafafe046e8c56ebb0d27b15ad03bda821a..28f4b230b8cbe44aea2dad385ab2b3e2d54811b3 100644 (file)
@@ -20,7 +20,6 @@ struct task_struct;   /* forward declaration for elf.h */
 #include <asm/pal.h>
 #include <asm/pgtable.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 
 #include "ssc.h"
 
index 0216e28300fad70af57562b7b1a74796703a0196..271f412bda1ad1c48f40dad7b72ee1171f169c19 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/io.h>
 #include <asm/pal.h>
 #include <asm/sal.h>
+#include <asm/setup.h>
 
 #include "ssc.h"
 
index a63218e1f6c98963967014662fcbff6d2f033573..c13064e422df6a28a1e544848376436bf4b8b54a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/skbuff.h>
 #include <linux/notifier.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/hpsim.h>
 
index a06dfb13d518cbf350f70df5c68621ef65a145c3..301609c3fceca4099201c06ef2b4992f7a29fff2 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <linux/init.h>
 #include <linux/numa.h>
-#include <asm/system.h>
 #include <asm/numa.h>
 
 #define COMPILER_DEPENDENT_INT64       long
index 3fad89ee01cb0e89c3b6872bd5d24d0b924ed791..7d9116600a3615d90333ddca4f49dff356b510f1 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/types.h>
 
 #include <asm/intrinsics.h>
-#include <asm/system.h>
 
 
 #define ATOMIC_INIT(i)         ((atomic_t) { (i) })
index 23cebe5685b9cdbd09cbabc286c74856e87fe7ca..58277fc650ef205954604394e9dc6ccda93fdd06 100644 (file)
@@ -8,4 +8,6 @@
 #define AT_SYSINFO     32
 #define AT_SYSINFO_EHDR        33
 
+#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
+
 #endif /* _ASM_IA64_AUXVEC_H */
diff --git a/arch/ia64/include/asm/barrier.h b/arch/ia64/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..60576e0
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Memory barrier definitions.  This is based on information published
+ * in the Processor Abstraction Layer and the System Abstraction Layer
+ * manual.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#ifndef _ASM_IA64_BARRIER_H
+#define _ASM_IA64_BARRIER_H
+
+#include <linux/compiler.h>
+
+/*
+ * Macros to force memory ordering.  In these descriptions, "previous"
+ * and "subsequent" refer to program order; "visible" means that all
+ * architecturally visible effects of a memory access have occurred
+ * (at a minimum, this means the memory has been read or written).
+ *
+ *   wmb():    Guarantees that all preceding stores to memory-
+ *             like regions are visible before any subsequent
+ *             stores and that all following stores will be
+ *             visible only after all previous stores.
+ *   rmb():    Like wmb(), but for reads.
+ *   mb():     wmb()/rmb() combo, i.e., all previous memory
+ *             accesses are visible before all subsequent
+ *             accesses and vice versa.  This is also known as
+ *             a "fence."
+ *
+ * Note: "mb()" and its variants cannot be used as a fence to order
+ * accesses to memory mapped I/O registers.  For that, mf.a needs to
+ * be used.  However, we don't want to always use mf.a because (a)
+ * it's (presumably) much slower than mf and (b) mf.a is supported for
+ * sequential memory pages only.
+ */
+#define mb()   ia64_mf()
+#define rmb()  mb()
+#define wmb()  mb()
+#define read_barrier_depends() do { } while(0)
+
+#ifdef CONFIG_SMP
+# define smp_mb()      mb()
+# define smp_rmb()     rmb()
+# define smp_wmb()     wmb()
+# define smp_read_barrier_depends()    read_barrier_depends()
+#else
+# define smp_mb()      barrier()
+# define smp_rmb()     barrier()
+# define smp_wmb()     barrier()
+# define smp_read_barrier_depends()    do { } while(0)
+#endif
+
+/*
+ * XXX check on this ---I suspect what Linus really wants here is
+ * acquire vs release semantics but we can't discuss this stuff with
+ * Linus just yet.  Grrr...
+ */
+#define set_mb(var, value)     do { (var) = (value); mb(); } while (0)
+
+/*
+ * The group barrier in front of the rsm & ssm are necessary to ensure
+ * that none of the previous instructions in the same group are
+ * affected by the rsm/ssm.
+ */
+
+#endif /* _ASM_IA64_BARRIER_H */
diff --git a/arch/ia64/include/asm/cmpxchg.h b/arch/ia64/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..507c66c
--- /dev/null
@@ -0,0 +1 @@
+/* Future home of xchg() and cmpxchg() */
diff --git a/arch/ia64/include/asm/exec.h b/arch/ia64/include/asm/exec.h
new file mode 100644 (file)
index 0000000..b262424
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Process execution defines.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#ifndef _ASM_IA64_EXEC_H
+#define _ASM_IA64_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_IA64_EXEC_H */
index 8428525ddb225de4cf1ea49eb783b3f64d34e4a0..0ab82cc2dc8fe990f79d7db76f166b94e75b11d9 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/system.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
 do {                                                                   \
index e5a6c3530c6cbeca311bdc40108d4e51bc51d5cc..2c26321c28c3c0f504503c3d64421c95824bd585 100644 (file)
@@ -71,7 +71,6 @@ extern unsigned int num_io_spaces;
 #include <asm/intrinsics.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm-generic/iomap.h>
 
 /*
index f82d6be2ecd2105a37ba18cfc65bfef9af1367c5..2b68d856dc782c4c61b6b729f67a4a1b74eeb869 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef _ASM_IA64_IRQFLAGS_H
 #define _ASM_IA64_IRQFLAGS_H
 
+#include <asm/pal.h>
+
 #ifdef CONFIG_IA64_DEBUG_IRQ
 extern unsigned long last_cli_ip;
 static inline void arch_maybe_save_ip(unsigned long flags)
index e1d58f819d78bd7df803d4c3b7cb555281cc4d18..aea2b81b03a3c89f6faaa5da09db1c364e145dd9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_IA64_KEXEC_H
 #define _ASM_IA64_KEXEC_H
 
+#include <asm/setup.h>
 
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
index bc90c75adf6716f8423fe92935fa9fbd7be89cf2..b9f82c84f0932cff844ca97d09c3a6291c92e908 100644 (file)
@@ -261,4 +261,8 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
 #endif
index 2689ee54a1c92ec20b10f248f42b280f81fe8535..e35b3a84a40bb8fd4cdc688000fde06484ef8956 100644 (file)
@@ -459,6 +459,9 @@ struct kvm_sal_data {
        unsigned long boot_gp;
 };
 
+struct kvm_arch_memory_slot {
+};
+
 struct kvm_arch {
        spinlock_t dirty_log_lock;
 
index dd2a5b134390682b571be17cf5b2689bd2f7bfdc..13c1d4994d4951413d1d2aaf1c7c9ad16bdd18d9 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef _ASM_IA64_MCA_ASM_H
 #define _ASM_IA64_MCA_ASM_H
 
+#include <asm/percpu.h>
+
 #define PSR_IC         13
 #define PSR_I          14
 #define        PSR_DT          17
index 961a16f43e6b9d2f7e1c845a4fedf493f28b57ca..f1e1b2e3cdb3890cd8b35b0224eacbbafa94fe01 100644 (file)
@@ -221,4 +221,14 @@ get_order (unsigned long size)
                                         (((current->personality & READ_IMPLIES_EXEC) != 0)     \
                                          ? VM_EXEC : 0))
 
+#define GATE_ADDR              RGN_BASE(RGN_GATE)
+
+/*
+ * 0xa000000000000000+2*PERCPU_PAGE_SIZE
+ * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
+ */
+#define KERNEL_START            (GATE_ADDR+__IA64_UL_CONST(0x100000000))
+#define PERCPU_ADDR            (-PERCPU_PAGE_SIZE)
+#define LOAD_OFFSET            (KERNEL_START - KERNEL_TR_PAGE_SIZE)
+
 #endif /* _ASM_IA64_PAGE_H */
index b22e5f5fa5939ea0ab41ba929b7bfddf0d9c122e..5e04b591e423d09e21f5899523565aec2fa6771d 100644 (file)
 #include <asm/scatterlist.h>
 #include <asm/hw_irq.h>
 
+struct pci_vector_struct {
+       __u16 segment;  /* PCI Segment number */
+       __u16 bus;      /* PCI Bus number */
+       __u32 pci_id;   /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
+       __u8 pin;       /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
+       __u32 irq;      /* IRQ assigned */
+};
+
 /*
  * Can be used to override the logic in pci_scan_bus for skipping already-configured bus
  * numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the
index 1a97af31ef176e71d8138250c03c52b7ab0adf3f..815810cbbedccdb4a3043e186e67904a27c9c471 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/mman.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/types.h>
 
 #define IA64_MAX_PHYS_BITS     50      /* max. number of physical address bits (architected) */
index 17885567b731490670cdf0fd3562ec8fc2cac79a..7323ab9467ebae726473512588d2c8f41d0ceb40 100644 (file)
 #ifndef _ASM_IA64_POSIX_TYPES_H
 #define _ASM_IA64_POSIX_TYPES_H
 
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- *
- * Based on <asm-alpha/posix_types.h>.
- *
- * Modified 1998-2000, 2003
- *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-typedef unsigned long  __kernel_ino_t;
-typedef unsigned int   __kernel_mode_t;
 typedef unsigned int   __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef long long      __kernel_loff_t;
-typedef int            __kernel_pid_t;
-typedef int            __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
-typedef long           __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned long  __kernel_sigset_t;      /* at least 32 bits */
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
-
-typedef unsigned int   __kernel_old_dev_t;
-
-# ifdef __KERNEL__
-
-#  ifndef __GNUC__
-
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define        __FD_ISSET(d, set)      (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
-#define        __FD_ZERO(set)  \
-  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
+#define __kernel_nlink_t __kernel_nlink_t
 
-#  else /* !__GNUC__ */
-
-/* With GNU C, use inline functions instead so args are evaluated only once: */
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, const __kernel_fd_set *p)
-{ 
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
-{
-       unsigned long *tmp = p->fds_bits;
-       int i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-                     case 16:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-                       tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                       return;
-
-                     case 8:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       return;
+typedef unsigned long  __kernel_sigset_t;      /* at least 32 bits */
 
-                     case 4:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       return;
-               }
-       }
-       i = __FDSET_LONGS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
+#include <asm-generic/posix_types.h>
 
-#  endif /* !__GNUC__ */
-# endif /* __KERNEL__ */
 #endif /* _ASM_IA64_POSIX_TYPES_H */
index 691be0b95c1e0fb280721cde45e9d1f88d08af77..483f6c6a4238d176eb449953ce0f157c2232cb12 100644 (file)
@@ -19,6 +19,9 @@
 #include <asm/ptrace.h>
 #include <asm/ustack.h>
 
+#define __ARCH_WANT_UNLOCKED_CTXSW
+#define ARCH_HAS_PREFETCH_SWITCH_STACK
+
 #define IA64_NUM_PHYS_STACK_REG        96
 #define IA64_NUM_DBG_REGS      8
 
@@ -720,6 +723,11 @@ extern unsigned long boot_option_idle_override;
 enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
                         IDLE_NOMWAIT, IDLE_POLL};
 
+void cpu_idle_wait(void);
+void default_idle(void);
+
+#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PROCESSOR_H */
index d19ddba4e32771bdd5d5452e0b9cf6804e86dbb1..e504f382115eebcc26e62d3123a74bff10b72025 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/efi.h>
 
 #include <asm/pal.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 
 extern spinlock_t sal_lock;
index 4399a44355b3f674a676e4d606a481b80d5a41e6..8d56458310b316406a0b69aabc3839de23f9ebf0 100644 (file)
@@ -3,4 +3,22 @@
 
 #define COMMAND_LINE_SIZE      2048
 
+extern struct ia64_boot_param {
+       __u64 command_line;             /* physical address of command line arguments */
+       __u64 efi_systab;               /* physical address of EFI system table */
+       __u64 efi_memmap;               /* physical address of EFI memory map */
+       __u64 efi_memmap_size;          /* size of EFI memory map */
+       __u64 efi_memdesc_size;         /* size of an EFI memory map descriptor */
+       __u32 efi_memdesc_version;      /* memory descriptor version */
+       struct {
+               __u16 num_cols; /* number of columns on console output device */
+               __u16 num_rows; /* number of rows on console output device */
+               __u16 orig_x;   /* cursor's x position */
+               __u16 orig_y;   /* cursor's y position */
+       } console_info;
+       __u64 fpswa;            /* physical address of the fpswa interface */
+       __u64 initrd_start;
+       __u64 initrd_size;
+} *ia64_boot_param;
+
 #endif
index 1c5108d44d8bf9f4ced5a99577546e650dfc95d2..22ae358c8d16dd7d97d245b103e49f31d27c414e 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/cache.h>
 #include <asm/percpu.h>
-#include <asm/system.h>
 
 
 /*
index b77768d35f93fbfe76d933770d97d68a579e4053..54ff557d474e49a2376cefe8a78e646fda36cc78 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/atomic.h>
 #include <asm/intrinsics.h>
-#include <asm/system.h>
 
 #define arch_spin_lock_init(x)                 ((x)->lock = 0)
 
diff --git a/arch/ia64/include/asm/switch_to.h b/arch/ia64/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..cb2412f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Low-level task switching. This is based on information published in
+ * the Processor Abstraction Layer and the System Abstraction Layer
+ * manual.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#ifndef _ASM_IA64_SWITCH_TO_H
+#define _ASM_IA64_SWITCH_TO_H
+
+#include <linux/percpu.h>
+
+struct task_struct;
+
+/*
+ * Context switch from one thread to another.  If the two threads have
+ * different address spaces, schedule() has already taken care of
+ * switching to the new address space by calling switch_mm().
+ *
+ * Disabling access to the fph partition and the debug-register
+ * context switch MUST be done before calling ia64_switch_to() since a
+ * newly created thread returns directly to
+ * ia64_ret_from_syscall_clear_r8.
+ */
+extern struct task_struct *ia64_switch_to (void *next_task);
+
+extern void ia64_save_extra (struct task_struct *task);
+extern void ia64_load_extra (struct task_struct *task);
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
+# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
+#else
+# define IA64_ACCOUNT_ON_SWITCH(p,n)
+#endif
+
+#ifdef CONFIG_PERFMON
+  DECLARE_PER_CPU(unsigned long, pfm_syst_info);
+# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
+#else
+# define PERFMON_IS_SYSWIDE() (0)
+#endif
+
+#define IA64_HAS_EXTRA_STATE(t)                                                        \
+       ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)       \
+        || PERFMON_IS_SYSWIDE())
+
+#define __switch_to(prev,next,last) do {                                                        \
+       IA64_ACCOUNT_ON_SWITCH(prev, next);                                                      \
+       if (IA64_HAS_EXTRA_STATE(prev))                                                          \
+               ia64_save_extra(prev);                                                           \
+       if (IA64_HAS_EXTRA_STATE(next))                                                          \
+               ia64_load_extra(next);                                                           \
+       ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next);                      \
+       (last) = ia64_switch_to((next));                                                         \
+} while (0)
+
+#ifdef CONFIG_SMP
+/*
+ * In the SMP case, we save the fph state when context-switching away from a thread that
+ * modified fph.  This way, when the thread gets scheduled on another CPU, the CPU can
+ * pick up the state from task->thread.fph, avoiding the complication of having to fetch
+ * the latest fph state from another CPU.  In other words: eager save, lazy restore.
+ */
+# define switch_to(prev,next,last) do {                                                \
+       if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) {                               \
+               ia64_psr(task_pt_regs(prev))->mfh = 0;                  \
+               (prev)->thread.flags |= IA64_THREAD_FPH_VALID;                  \
+               __ia64_save_fpu((prev)->thread.fph);                            \
+       }                                                                       \
+       __switch_to(prev, next, last);                                          \
+       /* "next" in old context is "current" in new context */                 \
+       if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) &&        \
+                    (task_cpu(current) !=                                     \
+                                     task_thread_info(current)->last_cpu))) { \
+               platform_migrate(current);                                     \
+               task_thread_info(current)->last_cpu = task_cpu(current);       \
+       }                                                                      \
+} while (0)
+#else
+# define switch_to(prev,next,last)     __switch_to(prev, next, last)
+#endif
+
+#endif /* _ASM_IA64_SWITCH_TO_H */
diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h
deleted file mode 100644 (file)
index 6cca307..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-#ifndef _ASM_IA64_SYSTEM_H
-#define _ASM_IA64_SYSTEM_H
-
-/*
- * System defines. Note that this is included both from .c and .S
- * files, so it does only defines, not any C code.  This is based
- * on information published in the Processor Abstraction Layer
- * and the System Abstraction Layer manual.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- *     David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-
-#include <asm/kregs.h>
-#include <asm/page.h>
-#include <asm/pal.h>
-#include <asm/percpu.h>
-
-#define GATE_ADDR              RGN_BASE(RGN_GATE)
-
-/*
- * 0xa000000000000000+2*PERCPU_PAGE_SIZE
- * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
- */
-#define KERNEL_START            (GATE_ADDR+__IA64_UL_CONST(0x100000000))
-#define PERCPU_ADDR            (-PERCPU_PAGE_SIZE)
-#define LOAD_OFFSET            (KERNEL_START - KERNEL_TR_PAGE_SIZE)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
-
-struct pci_vector_struct {
-       __u16 segment;  /* PCI Segment number */
-       __u16 bus;      /* PCI Bus number */
-       __u32 pci_id;   /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
-       __u8 pin;       /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
-       __u32 irq;      /* IRQ assigned */
-};
-
-extern struct ia64_boot_param {
-       __u64 command_line;             /* physical address of command line arguments */
-       __u64 efi_systab;               /* physical address of EFI system table */
-       __u64 efi_memmap;               /* physical address of EFI memory map */
-       __u64 efi_memmap_size;          /* size of EFI memory map */
-       __u64 efi_memdesc_size;         /* size of an EFI memory map descriptor */
-       __u32 efi_memdesc_version;      /* memory descriptor version */
-       struct {
-               __u16 num_cols; /* number of columns on console output device */
-               __u16 num_rows; /* number of rows on console output device */
-               __u16 orig_x;   /* cursor's x position */
-               __u16 orig_y;   /* cursor's y position */
-       } console_info;
-       __u64 fpswa;            /* physical address of the fpswa interface */
-       __u64 initrd_start;
-       __u64 initrd_size;
-} *ia64_boot_param;
-
-/*
- * Macros to force memory ordering.  In these descriptions, "previous"
- * and "subsequent" refer to program order; "visible" means that all
- * architecturally visible effects of a memory access have occurred
- * (at a minimum, this means the memory has been read or written).
- *
- *   wmb():    Guarantees that all preceding stores to memory-
- *             like regions are visible before any subsequent
- *             stores and that all following stores will be
- *             visible only after all previous stores.
- *   rmb():    Like wmb(), but for reads.
- *   mb():     wmb()/rmb() combo, i.e., all previous memory
- *             accesses are visible before all subsequent
- *             accesses and vice versa.  This is also known as
- *             a "fence."
- *
- * Note: "mb()" and its variants cannot be used as a fence to order
- * accesses to memory mapped I/O registers.  For that, mf.a needs to
- * be used.  However, we don't want to always use mf.a because (a)
- * it's (presumably) much slower than mf and (b) mf.a is supported for
- * sequential memory pages only.
- */
-#define mb()   ia64_mf()
-#define rmb()  mb()
-#define wmb()  mb()
-#define read_barrier_depends() do { } while(0)
-
-#ifdef CONFIG_SMP
-# define smp_mb()      mb()
-# define smp_rmb()     rmb()
-# define smp_wmb()     wmb()
-# define smp_read_barrier_depends()    read_barrier_depends()
-#else
-# define smp_mb()      barrier()
-# define smp_rmb()     barrier()
-# define smp_wmb()     barrier()
-# define smp_read_barrier_depends()    do { } while(0)
-#endif
-
-/*
- * XXX check on this ---I suspect what Linus really wants here is
- * acquire vs release semantics but we can't discuss this stuff with
- * Linus just yet.  Grrr...
- */
-#define set_mb(var, value)     do { (var) = (value); mb(); } while (0)
-
-/*
- * The group barrier in front of the rsm & ssm are necessary to ensure
- * that none of the previous instructions in the same group are
- * affected by the rsm/ssm.
- */
-
-#ifdef __KERNEL__
-
-/*
- * Context switch from one thread to another.  If the two threads have
- * different address spaces, schedule() has already taken care of
- * switching to the new address space by calling switch_mm().
- *
- * Disabling access to the fph partition and the debug-register
- * context switch MUST be done before calling ia64_switch_to() since a
- * newly created thread returns directly to
- * ia64_ret_from_syscall_clear_r8.
- */
-extern struct task_struct *ia64_switch_to (void *next_task);
-
-struct task_struct;
-
-extern void ia64_save_extra (struct task_struct *task);
-extern void ia64_load_extra (struct task_struct *task);
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
-# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
-#else
-# define IA64_ACCOUNT_ON_SWITCH(p,n)
-#endif
-
-#ifdef CONFIG_PERFMON
-  DECLARE_PER_CPU(unsigned long, pfm_syst_info);
-# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
-#else
-# define PERFMON_IS_SYSWIDE() (0)
-#endif
-
-#define IA64_HAS_EXTRA_STATE(t)                                                        \
-       ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)       \
-        || PERFMON_IS_SYSWIDE())
-
-#define __switch_to(prev,next,last) do {                                                        \
-       IA64_ACCOUNT_ON_SWITCH(prev, next);                                                      \
-       if (IA64_HAS_EXTRA_STATE(prev))                                                          \
-               ia64_save_extra(prev);                                                           \
-       if (IA64_HAS_EXTRA_STATE(next))                                                          \
-               ia64_load_extra(next);                                                           \
-       ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next);                      \
-       (last) = ia64_switch_to((next));                                                         \
-} while (0)
-
-#ifdef CONFIG_SMP
-/*
- * In the SMP case, we save the fph state when context-switching away from a thread that
- * modified fph.  This way, when the thread gets scheduled on another CPU, the CPU can
- * pick up the state from task->thread.fph, avoiding the complication of having to fetch
- * the latest fph state from another CPU.  In other words: eager save, lazy restore.
- */
-# define switch_to(prev,next,last) do {                                                \
-       if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) {                               \
-               ia64_psr(task_pt_regs(prev))->mfh = 0;                  \
-               (prev)->thread.flags |= IA64_THREAD_FPH_VALID;                  \
-               __ia64_save_fpu((prev)->thread.fph);                            \
-       }                                                                       \
-       __switch_to(prev, next, last);                                          \
-       /* "next" in old context is "current" in new context */                 \
-       if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) &&        \
-                    (task_cpu(current) !=                                     \
-                                     task_thread_info(current)->last_cpu))) { \
-               platform_migrate(current);                                     \
-               task_thread_info(current)->last_cpu = task_cpu(current);       \
-       }                                                                      \
-} while (0)
-#else
-# define switch_to(prev,next,last)     __switch_to(prev, next, last)
-#endif
-
-#define __ARCH_WANT_UNLOCKED_CTXSW
-#define ARCH_HAS_PREFETCH_SWITCH_STACK
-#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
-
-void cpu_idle_wait(void);
-
-#define arch_align_stack(x) (x)
-
-void default_idle(void);
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_IA64_SYSTEM_H */
index 61b5bdfd980ee019668ce263efc00d4bb89de071..8f6cbaa742e9c02c308c2c07f9b7ca1471bdd49d 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_UV_UV_H
 #define _ASM_IA64_UV_UV_H
 
-#include <asm/system.h>
 #include <asm/sn/simulator.h>
 
 static inline int is_uv_system(void)
index 2d801bfe16ac10b0aab83ade247c5474123d56f1..ac795d311f4411cef9cd8c76b1e91cc6b7d5988c 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/iosapic.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/numa.h>
 #include <asm/sal.h>
 #include <asm/cyclone.h>
@@ -844,7 +843,7 @@ early_param("additional_cpus", setup_additional_cpus);
  * are onlined, or offlined. The reason is per-cpu data-structures
  * are allocated by some modules at init time, and dont expect to
  * do this dynamically on cpu arrival/departure.
- * cpu_present_map on the other hand can change dynamically.
+ * cpu_present_mask on the other hand can change dynamically.
  * In case when cpu_hotplug is not compiled, then we resort to current
  * behaviour, which is cpu_possible == cpu_present.
  * - Ashok Raj
@@ -922,7 +921,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
 
        acpi_map_cpu2node(handle, cpu, physid);
 
-       cpu_set(cpu, cpu_present_map);
+       set_cpu_present(cpu, true);
        ia64_cpu_to_sapicid[cpu] = physid;
 
        acpi_processor_set_pdc(handle);
@@ -941,7 +940,7 @@ EXPORT_SYMBOL(acpi_map_lsapic);
 int acpi_unmap_lsapic(int cpu)
 {
        ia64_cpu_to_sapicid[cpu] = -1;
-       cpu_clear(cpu, cpu_present_map);
+       set_cpu_present(cpu, false);
 
 #ifdef CONFIG_ACPI_NUMA
        /* NUMA specific cleanup's */
index af56501690432110a1f27847bea9dffd60737b81..a48bd9a9927bb3b42c7b2076bb0c4b359d83a2e5 100644 (file)
@@ -269,8 +269,8 @@ void foo(void)
        BLANK();
 
        /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
-       DEFINE(IA64_GTOD_LOCK_OFFSET,
-               offsetof (struct fsyscall_gtod_data_t, lock));
+       DEFINE(IA64_GTOD_SEQ_OFFSET,
+              offsetof (struct fsyscall_gtod_data_t, seq));
        DEFINE(IA64_GTOD_WALL_TIME_OFFSET,
                offsetof (struct fsyscall_gtod_data_t, wall_time));
        DEFINE(IA64_GTOD_MONO_TIME_OFFSET,
index c38d22e5e902f9764e1963ed7f65638f3a419d10..d37bbd48637fd80f52f01b3a0592f341feabb030 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mca.h>
+#include <asm/setup.h>
 #include <asm/tlbflush.h>
 
 #define EFI_DEBUG      0
index 331d42bda77ae97f457b13f970aa83c40e11d4b0..cc26edac0ec6e7768f25f1ea6ed60ca2d8d143a1 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/thread_info.h>
 #include <asm/sal.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
 
 #include "entry.h"
@@ -174,7 +173,7 @@ ENTRY(fsys_set_tid_address)
        FSYS_RETURN
 END(fsys_set_tid_address)
 
-#if IA64_GTOD_LOCK_OFFSET !=0
+#if IA64_GTOD_SEQ_OFFSET !=0
 #error fsys_gettimeofday incompatible with changes to struct fsyscall_gtod_data_t
 #endif
 #if IA64_ITC_JITTER_OFFSET !=0
index 57d2ee6c83e1e637cd5c587f165834f980fb38a7..146b15b5fec30f34d4c78df1a390870b34781aaa 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 struct fsyscall_gtod_data_t {
-       seqlock_t       lock;
+       seqcount_t      seq;
        struct timespec wall_time;
        struct timespec monotonic_time;
        cycle_t         clk_mask;
index 245d3e1ec7e1b00dc97f125f4ef0cc90e45b0aa8..b5f8bdd8618e6907e2548e682d2a0caf5b206c62 100644 (file)
@@ -11,8 +11,9 @@
 #include <asm/errno.h>
 #include <asm/asm-offsets.h>
 #include <asm/sigcontext.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
+#include <asm/kregs.h>
+#include <asm/page.h>
 #include "paravirt_inst.h"
 
 /*
index d32b0855110ae96e358547c9f0c835ae7000f0c2..e518f7902af6a3f9fb68fca9f8a2eb8c71e25baf 100644 (file)
@@ -5,8 +5,7 @@
  * its layout.
  */
 
-
-#include <asm/system.h>
+#include <asm/page.h>
 #include "paravirt_patchlist.h"
 
 SECTIONS
index 17a9fba38930ab0504aa7b17262765af117c2740..629a250f7c190376c6976d679f427044a0209eda 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/mca_asm.h>
 #include <linux/init.h>
 #include <linux/linkage.h>
index b0f9afebb1467d4e2eccf6c16601c7257f378620..ef4b5d877cf2ed08dc2706f5da6883323219aeb9 100644 (file)
@@ -98,7 +98,6 @@
 #include <asm/machvec.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #undef DEBUG_INTERRUPT_ROUTING
 
index 782c3a357f24f4d4417ce4a2499e63f1a09a0e3b..5c3e0888265a80a2fe75d48f6ed8177aeb3aad7f 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/hw_irq.h>
 #include <asm/machvec.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 
 #ifdef CONFIG_PERFMON
@@ -118,7 +117,7 @@ static inline int find_unassigned_vector(cpumask_t domain)
        cpumask_t mask;
        int pos, vector;
 
-       cpus_and(mask, domain, cpu_online_map);
+       cpumask_and(&mask, &domain, cpu_online_mask);
        if (cpus_empty(mask))
                return -EINVAL;
 
@@ -141,7 +140,7 @@ static int __bind_irq_vector(int irq, int vector, cpumask_t domain)
        BUG_ON((unsigned)irq >= NR_IRQS);
        BUG_ON((unsigned)vector >= IA64_NUM_VECTORS);
 
-       cpus_and(mask, domain, cpu_online_map);
+       cpumask_and(&mask, &domain, cpu_online_mask);
        if (cpus_empty(mask))
                return -EINVAL;
        if ((cfg->vector == vector) && cpus_equal(cfg->domain, domain))
@@ -179,7 +178,7 @@ static void __clear_irq_vector(int irq)
        BUG_ON(cfg->vector == IRQ_VECTOR_UNASSIGNED);
        vector = cfg->vector;
        domain = cfg->domain;
-       cpus_and(mask, cfg->domain, cpu_online_map);
+       cpumask_and(&mask, &cfg->domain, cpu_online_mask);
        for_each_cpu_mask(cpu, mask)
                per_cpu(vector_irq, cpu)[vector] = -1;
        cfg->vector = IRQ_VECTOR_UNASSIGNED;
@@ -322,7 +321,7 @@ void irq_complete_move(unsigned irq)
        if (unlikely(cpu_isset(smp_processor_id(), cfg->old_domain)))
                return;
 
-       cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+       cpumask_and(&cleanup_mask, &cfg->old_domain, cpu_online_mask);
        cfg->move_cleanup_count = cpus_weight(cleanup_mask);
        for_each_cpu_mask(i, cleanup_mask)
                platform_send_ipi(i, IA64_IRQ_MOVE_VECTOR, IA64_IPI_DM_INT, 0);
index d93e396bf5998813114d0ac1cbbd92551d964551..fa25689fc453b36e1cb455782af442bdbf8017ee 100644 (file)
@@ -54,7 +54,6 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
index d41a40ef80c074575a5f5706011b22a563b4e99d..f5a1e5246b3e02e3f1039c848c894407b6e273b2 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <asm/machvec.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_IA64_GENERIC
 
index 8192009cb92470b3b040653fce1c7311456504a8..65bf9cd390443c3574e8d4da5a175c566928b535 100644 (file)
@@ -92,7 +92,6 @@
 #include <asm/meminit.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/sal.h>
 #include <asm/mca.h>
 #include <asm/kexec.h>
@@ -1515,7 +1514,8 @@ static void
 ia64_mca_cmc_poll (unsigned long dummy)
 {
        /* Trigger a CMC interrupt cascade  */
-       platform_send_ipi(first_cpu(cpu_online_map), IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
+       platform_send_ipi(cpumask_first(cpu_online_mask), IA64_CMCP_VECTOR,
+                                                       IA64_IPI_DM_INT, 0);
 }
 
 /*
@@ -1591,7 +1591,8 @@ static void
 ia64_mca_cpe_poll (unsigned long dummy)
 {
        /* Trigger a CPE interrupt cascade  */
-       platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
+       platform_send_ipi(cpumask_first(cpu_online_mask), IA64_CPEP_VECTOR,
+                                                       IA64_IPI_DM_INT, 0);
 }
 
 #endif /* CONFIG_ACPI */
index 09b4d6828c4544f6088aab1561b897cab083c1f4..1c2e894067219a9c0d68cae7e00db6e5b6749a0a 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/machvec.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/sal.h>
 #include <asm/mca.h>
 
index 94e0db72d4a68591370de63af9db07baaae203ab..fb2f1e622877e202f8bdb6be4d6922fa6431986f 100644 (file)
@@ -57,7 +57,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
                return irq;
 
        irq_set_msi_desc(irq, desc);
-       cpus_and(mask, irq_to_domain(irq), cpu_online_map);
+       cpumask_and(&mask, &(irq_to_domain(irq)), cpu_online_mask);
        dest_phys_id = cpu_physical_id(first_cpu(mask));
        vector = irq_to_vector(irq);
 
@@ -179,7 +179,7 @@ msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
        unsigned dest;
        cpumask_t mask;
 
-       cpus_and(mask, irq_to_domain(irq), cpu_online_map);
+       cpumask_and(&mask, &(irq_to_domain(irq)), cpu_online_mask);
        dest = cpu_physical_id(first_cpu(mask));
 
        msg->address_hi = 0;
index 68a1311db806b49a918c76ecea4af5ca75a55da0..1cf091793714dde033b74a3d696eceb8b1b737b3 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/patch.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
 
 /*
index eb11757200500f574aaf6665ea9c3f17b9a3d566..7cdc89b2483c9200e8cdda24d93062f14b7364b9 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/machvec.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 
 #ifdef CONFIG_INTEL_IOMMU
 
index b2c65e034f5da30f42ef4f8d7b76f3736883f974..9d0fd7d5bb82c03d65820a01b1af673c7b0c7c7e 100644 (file)
@@ -49,7 +49,6 @@
 #include <asm/perfmon.h>
 #include <asm/processor.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 
index 9dc52b63fc876d258955568782b1ace3c107d01d..ce74e143aea3b6eacf23d3f722ee07bee5f0c625 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sal.h>
+#include <asm/switch_to.h>
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 #include <asm/unwind.h>
index dad91661ddf96e8b54aa4fbeafb9190879a65ccf..4265ff64219b20eade95390e8cc2f47ec7500fba 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace_offsets.h>
 #include <asm/rse.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unwind.h>
 #ifdef CONFIG_PERFMON
index cd57d7312de0f597bb5a2a32f0db745ec8a67dbf..aaefd9b94f2fc6f57865b5d500bceaf50fdc84b3 100644 (file)
@@ -59,7 +59,6 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/unistd.h>
 #include <asm/hpsim.h>
@@ -486,7 +485,7 @@ mark_bsp_online (void)
 {
 #ifdef CONFIG_SMP
        /* If we register an early console, allow CPU 0 to printk */
-       cpu_set(smp_processor_id(), cpu_online_map);
+       set_cpu_online(smp_processor_id(), true);
 #endif
 }
 
index 0bd537b4ea6b82629fe598b2370e4a8d098c89de..9fcd4e63048f65f5ae638833c7a51b756883acbb 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/unistd.h>
 #include <asm/mca.h>
@@ -77,7 +76,7 @@ stop_this_cpu(void)
        /*
         * Remove this CPU:
         */
-       cpu_clear(smp_processor_id(), cpu_online_map);
+       set_cpu_online(smp_processor_id(), false);
        max_xtp();
        local_irq_disable();
        cpu_halt();
index 559097986672f663cf1b612586a5646fc8aeb1d8..796f6a5b966a742d46a4f63417939e0a737a0732 100644 (file)
@@ -55,7 +55,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/unistd.h>
 #include <asm/sn/arch.h>
@@ -401,7 +400,7 @@ smp_callin (void)
        /* Setup the per cpu irq handling data structures */
        __setup_vector_irq(cpuid);
        notify_cpu_starting(cpuid);
-       cpu_set(cpuid, cpu_online_map);
+       set_cpu_online(cpuid, true);
        per_cpu(cpu_state, cpuid) = CPU_ONLINE;
        spin_unlock(&vector_lock);
        ipi_call_unlock_irq();
@@ -548,7 +547,7 @@ do_rest:
        if (!cpu_isset(cpu, cpu_callin_map)) {
                printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid);
                ia64_cpu_to_sapicid[cpu] = -1;
-               cpu_clear(cpu, cpu_online_map);  /* was set in smp_callin() */
+               set_cpu_online(cpu, false);  /* was set in smp_callin() */
                return -EINVAL;
        }
        return 0;
@@ -578,8 +577,7 @@ smp_build_cpu_map (void)
        }
 
        ia64_cpu_to_sapicid[0] = boot_cpu_id;
-       cpus_clear(cpu_present_map);
-       set_cpu_present(0, true);
+       init_cpu_present(cpumask_of(0));
        set_cpu_possible(0, true);
        for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
                sapicid = smp_boot_data.cpu_phys_id[i];
@@ -606,10 +604,6 @@ smp_prepare_cpus (unsigned int max_cpus)
 
        smp_setup_percpu_timer();
 
-       /*
-        * We have the boot CPU online for sure.
-        */
-       cpu_set(0, cpu_online_map);
        cpu_set(0, cpu_callin_map);
 
        local_cpu_data->loops_per_jiffy = loops_per_jiffy;
@@ -633,7 +627,7 @@ smp_prepare_cpus (unsigned int max_cpus)
 
 void __devinit smp_prepare_boot_cpu(void)
 {
-       cpu_set(smp_processor_id(), cpu_online_map);
+       set_cpu_online(smp_processor_id(), true);
        cpu_set(smp_processor_id(), cpu_callin_map);
        set_numa_node(cpu_to_node_map[smp_processor_id()]);
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
@@ -690,7 +684,7 @@ int migrate_platform_irqs(unsigned int cpu)
                        /*
                         * Now re-target the CPEI to a different processor
                         */
-                       new_cpei_cpu = any_online_cpu(cpu_online_map);
+                       new_cpei_cpu = cpumask_any(cpu_online_mask);
                        mask = cpumask_of(new_cpei_cpu);
                        set_cpei_target_cpu(new_cpei_cpu);
                        data = irq_get_irq_data(ia64_cpe_irq);
@@ -732,10 +726,10 @@ int __cpu_disable(void)
                        return -EBUSY;
        }
 
-       cpu_clear(cpu, cpu_online_map);
+       set_cpu_online(cpu, false);
 
        if (migrate_platform_irqs(cpu)) {
-               cpu_set(cpu, cpu_online_map);
+               set_cpu_online(cpu, true);
                return -EBUSY;
        }
 
index 43920de425f1efcac92203f84d4a67d8aa596457..ecc904b33c5f2935fa1285d8f4cdac9515a3a84d 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/sal.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 
 #include "fsyscall_gtod_data.h"
 
 static cycle_t itc_get_cycles(struct clocksource *cs);
 
-struct fsyscall_gtod_data_t fsyscall_gtod_data = {
-       .lock = __SEQLOCK_UNLOCKED(fsyscall_gtod_data.lock),
-};
+struct fsyscall_gtod_data_t fsyscall_gtod_data;
 
 struct itc_jitter_data_t itc_jitter_data;
 
@@ -460,9 +457,7 @@ void update_vsyscall_tz(void)
 void update_vsyscall(struct timespec *wall, struct timespec *wtm,
                        struct clocksource *c, u32 mult)
 {
-        unsigned long flags;
-
-        write_seqlock_irqsave(&fsyscall_gtod_data.lock, flags);
+       write_seqcount_begin(&fsyscall_gtod_data.seq);
 
         /* copy fsyscall clock data */
         fsyscall_gtod_data.clk_mask = c->mask;
@@ -485,6 +480,6 @@ void update_vsyscall(struct timespec *wall, struct timespec *wtm,
                fsyscall_gtod_data.monotonic_time.tv_sec++;
        }
 
-        write_sequnlock_irqrestore(&fsyscall_gtod_data.lock, flags);
+       write_seqcount_end(&fsyscall_gtod_data.seq);
 }
 
index 9deb21dbf62965740f2b6c34c1630dbf80d1f4aa..c64460b9c704d56e7cb5efd9fb750e251a9f707f 100644 (file)
@@ -220,7 +220,8 @@ static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf)
        ssize_t len;
        cpumask_t shared_cpu_map;
 
-       cpus_and(shared_cpu_map, this_leaf->shared_cpu_map, cpu_online_map);
+       cpumask_and(&shared_cpu_map,
+                               &this_leaf->shared_cpu_map, cpu_online_mask);
        len = cpumask_scnprintf(buf, NR_CPUS+1, &shared_cpu_map);
        len += sprintf(buf+len, "\n");
        return len;
index fd80e70018a959ebffdf860c962cf0ff062cc4f5..bd42b76000d153f9cfdaa14958fca4117880779d 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
+#include <asm/setup.h>
 
 fpswa_interface_t *fpswa_interface;
 EXPORT_SYMBOL(fpswa_interface);
index 6a867dc45c05b75af1a06e8f7eaaffc04249b96d..a96bcf83a735dae2f812f81e0fc54635bb3de072 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/gfp.h>
 #include <asm/page.h>
 #include <asm/pal.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <linux/atomic.h>
 #include <asm/tlbflush.h>
index fed6afa2e8a9014e65229e51e64fa4b1c13cc284..8f66195999e717a94f87b9f04c5116882be70fb5 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/ptrace_offsets.h>
 #include <asm/rse.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "entry.h"
index 53c0ba004e9eeeff2cf4f57bdceced9d69308aad..0ccb28fab27e7376bbf09be5a89c0b59078539e6 100644 (file)
@@ -1,7 +1,6 @@
 
 #include <asm/cache.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 
 #include <asm-generic/vmlinux.lds.h>
index 405052002493b8de11884c109afe9fcaf008aba2..f5104b7c52cd369b0150f9884133922ba6defe03 100644 (file)
@@ -809,10 +809,13 @@ static void kvm_build_io_pmt(struct kvm *kvm)
 #define GUEST_PHYSICAL_RR4     0x2739
 #define VMM_INIT_RR            0x1660
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        BUG_ON(!kvm);
 
+       if (type)
+               return -EINVAL;
+
        kvm->arch.is_sn2 = ia64_platform_is("sn2");
 
        kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
@@ -1169,6 +1172,11 @@ out:
 
 #define PALE_RESET_ENTRY    0x80000000ffffffb0UL
 
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
+{
+       return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL);
+}
+
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct kvm_vcpu *v;
@@ -1563,6 +1571,21 @@ out:
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                struct kvm_memory_slot *memslot,
                struct kvm_memory_slot old,
index 20b3593761282746777f2f27304e5ac03bdee1da..02d29c2a132a028f92c2c55e92fc36bbc5edfb2e 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 extern int die(char *, struct pt_regs *, long);
index 13df239dbed1682c74c5746ebdbaa7320054faec..0eab454867a23d799cd2fc5798f616cf2131104f 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/sal.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
index f7b798993cea0cab958427c5a09946eed673ef49..6a219a9460502dabc27d2e6853f1d750a2da7ddb 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 /*
  * For IA64 we need to perform a complex little dance to get both
index d1ce3200147c9465c2af3d69a79ba0cae20036c0..524df4295c90d06d327afedac7115ce284d4f3e6 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/machvec.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/sal.h>
 #include <asm/smp.h>
index 77db0b514fa47299801097d035dec02246602712..f82e7b462b7b1e3774dc8fe7d195a9426df23e3f 100644 (file)
@@ -33,9 +33,9 @@
 #include <asm/io.h>
 #include <asm/sal.h>
 #include <asm/machvec.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/vga.h>
+#include <asm/setup.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
index e6332881864374111440c339a0da72e55130ff40..20b88cb1881a93e87b57d4d7b3e04e0c907eaa74 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/nodemask.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_cpuid.h>
index e884ba4e031de4d1550cc2811a52a5a2c182db42..68c845411624a8699e9c6342ccf6b7bf90b4d580 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/smp.h>
index 0f8844e4936328275130f9b4a352c455a5a0a72e..abab8f99e9139a7822b22f166ffe3c6e03700863 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/clocksource.h>
 
 #include <asm/hw_irq.h>
-#include <asm/system.h>
 #include <asm/timex.h>
 
 #include <asm/sn/leds.h>
index 2f406f509d44d9ec4fd1b7deee382a5338dcda5a..14c1711238c0c0edf2c4a2e89250269376634d31 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/delay.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
index b820ed02ab9f67b0452136326da826e0cc977261..e29519ebe2d20b7306e974ff72be5fe0880b6ffa 100644 (file)
@@ -7,7 +7,6 @@
 #include <asm/processor.h>
 #include <asm/asmmacro.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/paravirt.h>
 #include <asm/xen/privop.h>
 #include <linux/elfnote.h>
index 1e7f29fb21f2037c67145d13fc9e487adc62f5fd..0d81697c326c26c990acfa4e54c851d030e581c6 100644 (file)
@@ -11,7 +11,8 @@
 
 #include <linux/types.h>
 #include <asm/assembler.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
+#include <asm/dcache_clear.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
diff --git a/arch/m32r/include/asm/barrier.h b/arch/m32r/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..6976621
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_BARRIER_H
+#define _ASM_M32R_BARRIER_H
+
+#define nop()  __asm__ __volatile__ ("nop" : : )
+
+/*
+ * Memory barrier.
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ */
+#define mb()   barrier()
+#define rmb()  mb()
+#define wmb()  mb()
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      b = 2;
+ *      memory_barrier();
+ *      p = &b;                         q = p;
+ *                                      read_barrier_depends();
+ *                                      d = *q;
+ * </programlisting>
+ *
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      a = 2;
+ *      memory_barrier();
+ *      b = 3;                          y = b;
+ *                                      read_barrier_depends();
+ *                                      x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends() do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+#endif /* _ASM_M32R_BARRIER_H */
index 6300f22cdbdbce380e7333f382dc70655ce73cd0..d3dea9ac7d4e3890636b8cefc1f0e9df5c685013 100644 (file)
 #endif
 
 #include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <asm/assembler.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
+#include <asm/dcache_clear.h>
 #include <asm/types.h>
 
 /*
diff --git a/arch/m32r/include/asm/cmpxchg.h b/arch/m32r/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..de651db
--- /dev/null
@@ -0,0 +1,221 @@
+#ifndef _ASM_M32R_CMPXCHG_H
+#define _ASM_M32R_CMPXCHG_H
+
+/*
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/irqflags.h>
+#include <asm/assembler.h>
+#include <asm/dcache_clear.h>
+
+extern void  __xchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long
+__xchg(unsigned long x, volatile void *ptr, int size)
+{
+       unsigned long flags;
+       unsigned long tmp = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+#ifndef CONFIG_SMP
+       case 1:
+               __asm__ __volatile__ (
+                       "ldb    %0, @%2 \n\t"
+                       "stb    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__ (
+                       "ldh    %0, @%2 \n\t"
+                       "sth    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__ (
+                       "ld     %0, @%2 \n\t"
+                       "st     %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+#else  /* CONFIG_SMP */
+       case 4:
+               __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%2")
+                       "lock   %0, @%2;        \n\t"
+                       "unlock %1, @%2;        \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr)
+                       : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+               );
+               break;
+#endif  /* CONFIG_SMP */
+       default:
+               __xchg_called_with_bad_pointer();
+       }
+
+       local_irq_restore(flags);
+
+       return (tmp);
+}
+
+#define xchg(ptr, x)                                                   \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+static __always_inline unsigned long
+__xchg_local(unsigned long x, volatile void *ptr, int size)
+{
+       unsigned long flags;
+       unsigned long tmp = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               __asm__ __volatile__ (
+                       "ldb    %0, @%2 \n\t"
+                       "stb    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__ (
+                       "ldh    %0, @%2 \n\t"
+                       "sth    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__ (
+                       "ld     %0, @%2 \n\t"
+                       "st     %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       default:
+               __xchg_called_with_bad_pointer();
+       }
+
+       local_irq_restore(flags);
+
+       return (tmp);
+}
+
+#define xchg_local(ptr, x)                                             \
+       ((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr),    \
+                       sizeof(*(ptr))))
+
+#define __HAVE_ARCH_CMPXCHG    1
+
+static inline unsigned long
+__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
+{
+       unsigned long flags;
+       unsigned int retval;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%1")
+                       M32R_LOCK" %0, @%1;     \n"
+               "       bne     %0, %2, 1f;     \n"
+                       M32R_UNLOCK" %3, @%1;   \n"
+               "       bra     2f;             \n"
+                "       .fillinsn              \n"
+               "1:"
+                       M32R_UNLOCK" %0, @%1;   \n"
+                "       .fillinsn              \n"
+               "2:"
+                       : "=&r" (retval)
+                       : "r" (p), "r" (old), "r" (new)
+                       : "cbit", "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif  /* CONFIG_CHIP_M32700_TS1 */
+               );
+       local_irq_restore(flags);
+
+       return retval;
+}
+
+static inline unsigned long
+__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
+                       unsigned int new)
+{
+       unsigned long flags;
+       unsigned int retval;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%1")
+                       "ld %0, @%1;            \n"
+               "       bne     %0, %2, 1f;     \n"
+                       "st %3, @%1;            \n"
+               "       bra     2f;             \n"
+               "       .fillinsn               \n"
+               "1:"
+                       "st %0, @%1;            \n"
+               "       .fillinsn               \n"
+               "2:"
+                       : "=&r" (retval)
+                       : "r" (p), "r" (old), "r" (new)
+                       : "cbit", "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif  /* CONFIG_CHIP_M32700_TS1 */
+               );
+       local_irq_restore(flags);
+
+       return retval;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+#if 0  /* we don't have __cmpxchg_u64 */
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+#endif /* 0 */
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                              \
+       ((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o),       \
+                       (unsigned long)(n), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_local_u32(ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                           \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),     \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* _ASM_M32R_CMPXCHG_H */
diff --git a/arch/m32r/include/asm/dcache_clear.h b/arch/m32r/include/asm/dcache_clear.h
new file mode 100644 (file)
index 0000000..a0ae06c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_DCACHE_CLEAR_H
+#define _ASM_M32R_DCACHE_CLEAR_H
+
+#ifdef CONFIG_CHIP_M32700_TS1
+#define DCACHE_CLEAR(reg0, reg1, addr)                         \
+       "seth   "reg1", #high(dcache_dummy);            \n\t"   \
+       "or3    "reg1", "reg1", #low(dcache_dummy);     \n\t"   \
+       "lock   "reg0", @"reg1";                        \n\t"   \
+       "add3   "reg0", "addr", #0x1000;                \n\t"   \
+       "ld     "reg0", @"reg0";                        \n\t"   \
+       "add3   "reg0", "addr", #0x2000;                \n\t"   \
+       "ld     "reg0", @"reg0";                        \n\t"   \
+       "unlock "reg0", @"reg1";                        \n\t"
+       /* FIXME: This workaround code cannot handle kernel modules
+        * correctly under SMP environment.
+        */
+#else  /* CONFIG_CHIP_M32700_TS1 */
+#define DCACHE_CLEAR(reg0, reg1, addr)
+#endif /* CONFIG_CHIP_M32700_TS1 */
+
+#endif /* _ASM_M32R_DCACHE_CLEAR_H */
diff --git a/arch/m32r/include/asm/exec.h b/arch/m32r/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c805dbd
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_EXEC_H
+#define _ASM_M32R_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_M32R_EXEC_H */
index 734bca87018a5f39ec1c35d2c75579c5d5c46e41..4045db3e4f6519593439c40edd65473739bc77eb 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/percpu.h>
 #include <asm/assembler.h>
-#include <asm/system.h>
 #include <asm/local.h>
 
 /*
index b309c58586377421e6def20f4dc5c240c69c55af..0195850e1f88698b7a6c29ffd8b807b9e38a5b53 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
+#define __kernel_uid_t __kernel_uid_t
 
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
 typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
-       unsigned long *__tmp = __p->fds_bits;
-       int __i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-               case 16:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       __tmp[ 8] = 0; __tmp[ 9] = 0;
-                       __tmp[10] = 0; __tmp[11] = 0;
-                       __tmp[12] = 0; __tmp[13] = 0;
-                       __tmp[14] = 0; __tmp[15] = 0;
-                       return;
-
-               case 8:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       return;
-
-               case 4:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       return;
-               }
-       }
-       __i = __FDSET_LONGS;
-       while (__i) {
-               __i--;
-               *__tmp = 0;
-               __tmp++;
-       }
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif  /* _ASM_M32R_POSIX_TYPES_H */
index b0ea2f26da3bc57e93956e053c04ef59af9857cd..fa13694eaae35f29233e3a477c5d6e2aebc95f5e 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/compiler.h>
 #include <linux/atomic.h>
+#include <asm/dcache_clear.h>
 #include <asm/page.h>
 
 /*
diff --git a/arch/m32r/include/asm/switch_to.h b/arch/m32r/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..4b262f7
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_SWITCH_TO_H
+#define _ASM_M32R_SWITCH_TO_H
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ *
+ * `next' and `prev' should be struct task_struct, but it isn't always defined
+ */
+
+#if defined(CONFIG_FRAME_POINTER) || \
+       !defined(CONFIG_SCHED_OMIT_FRAME_POINTER)
+#define M32R_PUSH_FP " push fp\n"
+#define M32R_POP_FP  " pop  fp\n"
+#else
+#define M32R_PUSH_FP ""
+#define M32R_POP_FP  ""
+#endif
+
+#define switch_to(prev, next, last)  do { \
+       __asm__ __volatile__ ( \
+               "       seth    lr, #high(1f)                           \n" \
+               "       or3     lr, lr, #low(1f)                        \n" \
+               "       st      lr, @%4  ; store old LR                 \n" \
+               "       ld      lr, @%5  ; load new LR                  \n" \
+                       M32R_PUSH_FP \
+               "       st      sp, @%2  ; store old SP                 \n" \
+               "       ld      sp, @%3  ; load new SP                  \n" \
+               "       push    %1  ; store `prev' on new stack         \n" \
+               "       jmp     lr                                      \n" \
+               "       .fillinsn                                       \n" \
+               "1:                                                     \n" \
+               "       pop     %0  ; restore `__last' from new stack   \n" \
+                       M32R_POP_FP \
+               : "=r" (last) \
+               : "0" (prev), \
+                 "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+                 "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+               : "memory", "lr" \
+       ); \
+} while(0)
+
+#endif /* _ASM_M32R_SWITCH_TO_H */
diff --git a/arch/m32r/include/asm/system.h b/arch/m32r/include/asm/system.h
deleted file mode 100644 (file)
index 13c4679..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-#ifndef _ASM_M32R_SYSTEM_H
-#define _ASM_M32R_SYSTEM_H
-
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
- */
-
-#include <linux/compiler.h>
-#include <linux/irqflags.h>
-#include <asm/assembler.h>
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.
- *
- * `next' and `prev' should be struct task_struct, but it isn't always defined
- */
-
-#if defined(CONFIG_FRAME_POINTER) || \
-       !defined(CONFIG_SCHED_OMIT_FRAME_POINTER)
-#define M32R_PUSH_FP " push fp\n"
-#define M32R_POP_FP  " pop  fp\n"
-#else
-#define M32R_PUSH_FP ""
-#define M32R_POP_FP  ""
-#endif
-
-#define switch_to(prev, next, last)  do { \
-       __asm__ __volatile__ ( \
-               "       seth    lr, #high(1f)                           \n" \
-               "       or3     lr, lr, #low(1f)                        \n" \
-               "       st      lr, @%4  ; store old LR                 \n" \
-               "       ld      lr, @%5  ; load new LR                  \n" \
-                       M32R_PUSH_FP \
-               "       st      sp, @%2  ; store old SP                 \n" \
-               "       ld      sp, @%3  ; load new SP                  \n" \
-               "       push    %1  ; store `prev' on new stack         \n" \
-               "       jmp     lr                                      \n" \
-               "       .fillinsn                                       \n" \
-               "1:                                                     \n" \
-               "       pop     %0  ; restore `__last' from new stack   \n" \
-                       M32R_POP_FP \
-               : "=r" (last) \
-               : "0" (prev), \
-                 "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
-                 "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
-               : "memory", "lr" \
-       ); \
-} while(0)
-
-#define nop()  __asm__ __volatile__ ("nop" : : )
-
-#define xchg(ptr, x)                                                   \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-#define xchg_local(ptr, x)                                             \
-       ((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr),    \
-                       sizeof(*(ptr))))
-
-extern void  __xchg_called_with_bad_pointer(void);
-
-#ifdef CONFIG_CHIP_M32700_TS1
-#define DCACHE_CLEAR(reg0, reg1, addr)                         \
-       "seth   "reg1", #high(dcache_dummy);            \n\t"   \
-       "or3    "reg1", "reg1", #low(dcache_dummy);     \n\t"   \
-       "lock   "reg0", @"reg1";                        \n\t"   \
-       "add3   "reg0", "addr", #0x1000;                \n\t"   \
-       "ld     "reg0", @"reg0";                        \n\t"   \
-       "add3   "reg0", "addr", #0x2000;                \n\t"   \
-       "ld     "reg0", @"reg0";                        \n\t"   \
-       "unlock "reg0", @"reg1";                        \n\t"
-       /* FIXME: This workaround code cannot handle kernel modules
-        * correctly under SMP environment.
-        */
-#else  /* CONFIG_CHIP_M32700_TS1 */
-#define DCACHE_CLEAR(reg0, reg1, addr)
-#endif /* CONFIG_CHIP_M32700_TS1 */
-
-static __always_inline unsigned long
-__xchg(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long flags;
-       unsigned long tmp = 0;
-
-       local_irq_save(flags);
-
-       switch (size) {
-#ifndef CONFIG_SMP
-       case 1:
-               __asm__ __volatile__ (
-                       "ldb    %0, @%2 \n\t"
-                       "stb    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 2:
-               __asm__ __volatile__ (
-                       "ldh    %0, @%2 \n\t"
-                       "sth    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 4:
-               __asm__ __volatile__ (
-                       "ld     %0, @%2 \n\t"
-                       "st     %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-#else  /* CONFIG_SMP */
-       case 4:
-               __asm__ __volatile__ (
-                       DCACHE_CLEAR("%0", "r4", "%2")
-                       "lock   %0, @%2;        \n\t"
-                       "unlock %1, @%2;        \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr)
-                       : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-                       , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
-               );
-               break;
-#endif  /* CONFIG_SMP */
-       default:
-               __xchg_called_with_bad_pointer();
-       }
-
-       local_irq_restore(flags);
-
-       return (tmp);
-}
-
-static __always_inline unsigned long
-__xchg_local(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long flags;
-       unsigned long tmp = 0;
-
-       local_irq_save(flags);
-
-       switch (size) {
-       case 1:
-               __asm__ __volatile__ (
-                       "ldb    %0, @%2 \n\t"
-                       "stb    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 2:
-               __asm__ __volatile__ (
-                       "ldh    %0, @%2 \n\t"
-                       "sth    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 4:
-               __asm__ __volatile__ (
-                       "ld     %0, @%2 \n\t"
-                       "st     %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       default:
-               __xchg_called_with_bad_pointer();
-       }
-
-       local_irq_restore(flags);
-
-       return (tmp);
-}
-
-#define __HAVE_ARCH_CMPXCHG    1
-
-static inline unsigned long
-__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
-{
-       unsigned long flags;
-       unsigned int retval;
-
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-                       DCACHE_CLEAR("%0", "r4", "%1")
-                       M32R_LOCK" %0, @%1;     \n"
-               "       bne     %0, %2, 1f;     \n"
-                       M32R_UNLOCK" %3, @%1;   \n"
-               "       bra     2f;             \n"
-                "       .fillinsn              \n"
-               "1:"
-                       M32R_UNLOCK" %0, @%1;   \n"
-                "       .fillinsn              \n"
-               "2:"
-                       : "=&r" (retval)
-                       : "r" (p), "r" (old), "r" (new)
-                       : "cbit", "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-                       , "r4"
-#endif  /* CONFIG_CHIP_M32700_TS1 */
-               );
-       local_irq_restore(flags);
-
-       return retval;
-}
-
-static inline unsigned long
-__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
-                       unsigned int new)
-{
-       unsigned long flags;
-       unsigned int retval;
-
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-                       DCACHE_CLEAR("%0", "r4", "%1")
-                       "ld %0, @%1;            \n"
-               "       bne     %0, %2, 1f;     \n"
-                       "st %3, @%1;            \n"
-               "       bra     2f;             \n"
-               "       .fillinsn               \n"
-               "1:"
-                       "st %0, @%1;            \n"
-               "       .fillinsn               \n"
-               "2:"
-                       : "=&r" (retval)
-                       : "r" (p), "r" (old), "r" (new)
-                       : "cbit", "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-                       , "r4"
-#endif  /* CONFIG_CHIP_M32700_TS1 */
-               );
-       local_irq_restore(flags);
-
-       return retval;
-}
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-#if 0  /* we don't have __cmpxchg_u64 */
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-#endif /* 0 */
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                              \
-       ((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o),       \
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_local_u32(ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                           \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),     \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif  /* __KERNEL__ */
-
-/*
- * Memory barrier.
- *
- * mb() prevents loads and stores being reordered across this point.
- * rmb() prevents loads being reordered across this point.
- * wmb() prevents stores being reordered across this point.
- */
-#define mb()   barrier()
-#define rmb()  mb()
-#define wmb()  mb()
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *      CPU 0                           CPU 1
- *
- *      b = 2;
- *      memory_barrier();
- *      p = &b;                         q = p;
- *                                      read_barrier_depends();
- *                                      d = *q;
- * </programlisting>
- *
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *      CPU 0                           CPU 1
- *
- *      a = 2;
- *      memory_barrier();
- *      b = 3;                          y = b;
- *                                      read_barrier_depends();
- *                                      x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_M32R_SYSTEM_H */
index 20743754f2b218fad41b16898beab57a687e1f90..4c03361537aa6b49f3e2ba144afd667cd6b75307 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 
index ee6a9199561ca8b46b3e8c633966c61f44e2d824..3bcb207e5b6d2611127ca3d85526735882db952a 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 888aab1157edaf1d13f6f2deee693ece3fb64ef2..80f18cc6f5473be787a92f8dbea0305a00a359d5 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/vt_kern.h>              /* For unblank_screen() */
 
 #include <asm/m32r.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 2c9aeb453847e2c33d899c195f1645a1d434e1e0..3cdfa9c1d0915b71969c0943b27da64e64156d53 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/module.h>
 
 #include <asm/m32r.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
index 34671d32cefc3daff49c2a05378a26769d6c15a1..e2dd778aeac76cacadee6954b534a774e6485260 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 1053e1cb7401771160f98a306ab0d59cade65016..9a4ba8a8589d722cf96f8d5a2c5a1e2ec4422c76 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 35130ac3f8d1931c089b3b31cdf913fb8de167af..767d2f4d6ded8e0a1738c5fc708586b30a9d0fac 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index f3ed6b60a5f8a271fadd73951268d3111f214405..76d665abf51e1cac475ae9a7983a9570a509d9cd 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 2408e356ad1062c88423f73f8c15df5e6791a207..a3646d4b05bddf67fb268727dbd0371488806a56 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 83b46b067a17386a401fa7ea867bfa13c8c1c0bc..f8373c0695248fc573b22136fc9e2bb2120a0d72 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 32660705f5fdf751741c0cd9ba87afafab56e248..cd0170483e83e0a049f79089a55e25f07685c457 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 0c7a1e8c77b055d3990a19dc729d5a701abdb848..dcde0ec777f6637a2cc418d88f7ce55418009323 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 61e5c54625aeee7dd2a3a206e38051c6430ea0bd..2559eefc6aff9c09a6dc703af3f7ec1f014067f1 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/amigahw.h>
 
 static unsigned short *snd_data;
index b95a451b1c3ae6292092efcf4ea24fc103e69eda..ee01b7a38e58882143a0baab95b986a58f222bae 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 8d3eafab1ffeb0f89aae3a64697aa47827a7b11b..0a30406b9442a4961b8f40fbc2832e0cc2079889 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/apollohw.h>
 #include <asm/irq.h>
index 8048e1b7e5528c9b9e50de5930350a375e6b5770..783d8f02360ddfe0e3a01dfce968fc7050e7070b 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/seq_file.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/atarihw.h>
index d266fe89c125e2297fa595140154ac9d2d7cf9a2..1c1181ebb947714b5ce80ec992ea3d148aa32818 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/module.h>
 
 #include <asm/atarihw.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/atariints.h>
index c4ac15c4f065ce97d0f86aafeb148efd5734e7ba..d8eb32747ac52b777fda6694c27c9ca69ba6542d 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
 #include <asm/atari_stram.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/hwtest.h>
 #include <asm/io.h>
index 81286476f7403c1a273350d686ea32d65f0b7533..0bf850a20ea28394742e364a018bd69895684d83 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/bcd.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index 1c4d4c7bf4d4a478c938635fbc698c3c0596d6a1..cf12a17dc289c5f9aa26090ede2db00d224cba0a 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 
 /*
index c87fe69b0728bdccab9d2081c2ed6be95be16dca..29a71be9fa5b11d2675861ecee0bfb1822c87c05 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/machdep.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/blinken.h>
 
index 4eba796c00d4ae0c22008a9058b9bb6267c37ac4..336e6173794f3a2c2b720d4b3ce87e8ddca7d67a 100644 (file)
@@ -2,7 +2,7 @@
 #define __ARCH_M68K_ATOMIC__
 
 #include <linux/types.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..445ce22
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _M68K_BARRIER_H
+#define _M68K_BARRIER_H
+
+/*
+ * Force strict CPU ordering.
+ * Not really required on m68k...
+ */
+#define nop()          do { asm volatile ("nop"); barrier(); } while (0)
+#define mb()           barrier()
+#define rmb()          barrier()
+#define wmb()          barrier()
+#define read_barrier_depends() ((void)0)
+#define set_mb(var, value)     ({ (var) = (value); wmb(); })
+
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     ((void)0)
+
+#endif /* _M68K_BARRIER_H */
diff --git a/arch/m68k/include/asm/cmpxchg.h b/arch/m68k/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..5c81d0e
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef __ARCH_M68K_CMPXCHG__
+#define __ARCH_M68K_CMPXCHG__
+
+#include <linux/irqflags.h>
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int);
+
+#ifndef CONFIG_RMW_INSNS
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       unsigned long flags, tmp;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               tmp = *(u8 *)ptr;
+               *(u8 *)ptr = x;
+               x = tmp;
+               break;
+       case 2:
+               tmp = *(u16 *)ptr;
+               *(u16 *)ptr = x;
+               x = tmp;
+               break;
+       case 4:
+               tmp = *(u32 *)ptr;
+               *(u32 *)ptr = x;
+               x = tmp;
+               break;
+       default:
+               tmp = __invalid_xchg_size(x, ptr, size);
+               break;
+       }
+
+       local_irq_restore(flags);
+       return x;
+}
+#else
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+       case 1:
+               __asm__ __volatile__
+                       ("moveb %2,%0\n\t"
+                        "1:\n\t"
+                        "casb %0,%1,%2\n\t"
+                        "jne 1b"
+                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__
+                       ("movew %2,%0\n\t"
+                        "1:\n\t"
+                        "casw %0,%1,%2\n\t"
+                        "jne 1b"
+                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__
+                       ("movel %2,%0\n\t"
+                        "1:\n\t"
+                        "casl %0,%1,%2\n\t"
+                        "jne 1b"
+                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       default:
+               x = __invalid_xchg_size(x, ptr, size);
+               break;
+       }
+       return x;
+}
+#endif
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+extern unsigned long __invalid_cmpxchg_size(volatile void *,
+                                           unsigned long, unsigned long, int);
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#ifdef CONFIG_RMW_INSNS
+#define __HAVE_ARCH_CMPXCHG    1
+
+static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 1:
+               __asm__ __volatile__ ("casb %0,%2,%1"
+                                     : "=d" (old), "=m" (*(char *)p)
+                                     : "d" (new), "0" (old), "m" (*(char *)p));
+               break;
+       case 2:
+               __asm__ __volatile__ ("casw %0,%2,%1"
+                                     : "=d" (old), "=m" (*(short *)p)
+                                     : "d" (new), "0" (old), "m" (*(short *)p));
+               break;
+       case 4:
+               __asm__ __volatile__ ("casl %0,%2,%1"
+                                     : "=d" (old), "=m" (*(int *)p)
+                                     : "d" (new), "0" (old), "m" (*(int *)p));
+               break;
+       default:
+               old = __invalid_cmpxchg_size(p, old, new, size);
+               break;
+       }
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                                 \
+       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg_local(ptr, o, n)                                           \
+       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#else
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif
+
+#endif /* __ARCH_M68K_CMPXCHG__ */
diff --git a/arch/m68k/include/asm/exec.h b/arch/m68k/include/asm/exec.h
new file mode 100644 (file)
index 0000000..0499adf
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _M68K_EXEC_H
+#define _M68K_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _M68K_EXEC_H */
index 98d0970d9badf054e056820818ed7e0e29ba01b1..6373093be72bb049f37f071468c3b6c73d6daafe 100644 (file)
@@ -7,55 +7,22 @@
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
+#define __kernel_uid_t __kernel_uid_t
 
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef __FD_CLR
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef __FD_ISSET
-#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif
index 32c45f84ac60d6f87b71ce76d1f04e390f026694..95231e2f9d646efb00181fbcac41d1cbc637002c 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/sun3x.h>
 
diff --git a/arch/m68k/include/asm/switch_to.h b/arch/m68k/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..16fd6b6
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _M68K_SWITCH_TO_H
+#define _M68K_SWITCH_TO_H
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.  This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+/*
+ * switch_to() saves the extra registers, that are not saved
+ * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
+ * a0-a1. Some of these are used by schedule() and its predecessors
+ * and so we might get see unexpected behaviors when a task returns
+ * with unexpected register values.
+ *
+ * syscall stores these registers itself and none of them are used
+ * by syscall after the function in the syscall has been called.
+ *
+ * Beware that resume now expects *next to be in d1 and the offset of
+ * tss to be in a1. This saves a few instructions as we no longer have
+ * to push them onto the stack and read them back right after.
+ *
+ * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
+ *
+ * Changed 96/09/19 by Andreas Schwab
+ * pass prev in a0, next in a1
+ */
+asmlinkage void resume(void);
+#define switch_to(prev,next,last) do { \
+  register void *_prev __asm__ ("a0") = (prev); \
+  register void *_next __asm__ ("a1") = (next); \
+  register void *_last __asm__ ("d1"); \
+  __asm__ __volatile__("jbsr resume" \
+                      : "=a" (_prev), "=a" (_next), "=d" (_last) \
+                      : "0" (_prev), "1" (_next) \
+                      : "d0", "d2", "d3", "d4", "d5"); \
+  (last) = _last; \
+} while (0)
+
+#endif /* _M68K_SWITCH_TO_H */
diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h
deleted file mode 100644 (file)
index 8dc6817..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef _M68K_SYSTEM_H
-#define _M68K_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/irqflags.h>
-#include <asm/segment.h>
-#include <asm/entry.h>
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1
- */
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) do { \
-  register void *_prev __asm__ ("a0") = (prev); \
-  register void *_next __asm__ ("a1") = (next); \
-  register void *_last __asm__ ("d1"); \
-  __asm__ __volatile__("jbsr resume" \
-                      : "=a" (_prev), "=a" (_next), "=d" (_last) \
-                      : "0" (_prev), "1" (_next) \
-                      : "d0", "d2", "d3", "d4", "d5"); \
-  (last) = _last; \
-} while (0)
-
-
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
-#define nop()          do { asm volatile ("nop"); barrier(); } while (0)
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value)     ({ (var) = (value); wmb(); })
-
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     ((void)0)
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#ifndef CONFIG_RMW_INSNS
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       unsigned long flags, tmp;
-
-       local_irq_save(flags);
-
-       switch (size) {
-       case 1:
-               tmp = *(u8 *)ptr;
-               *(u8 *)ptr = x;
-               x = tmp;
-               break;
-       case 2:
-               tmp = *(u16 *)ptr;
-               *(u16 *)ptr = x;
-               x = tmp;
-               break;
-       case 4:
-               tmp = *(u32 *)ptr;
-               *(u32 *)ptr = x;
-               x = tmp;
-               break;
-       default:
-               BUG();
-       }
-
-       local_irq_restore(flags);
-       return x;
-}
-#else
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-           case 1:
-               __asm__ __volatile__
-                       ("moveb %2,%0\n\t"
-                        "1:\n\t"
-                        "casb %0,%1,%2\n\t"
-                        "jne 1b"
-                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-               break;
-           case 2:
-               __asm__ __volatile__
-                       ("movew %2,%0\n\t"
-                        "1:\n\t"
-                        "casw %0,%1,%2\n\t"
-                        "jne 1b"
-                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-               break;
-           case 4:
-               __asm__ __volatile__
-                       ("movel %2,%0\n\t"
-                        "1:\n\t"
-                        "casl %0,%1,%2\n\t"
-                        "jne 1b"
-                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-               break;
-       }
-       return x;
-}
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-#ifdef CONFIG_RMW_INSNS
-#define __HAVE_ARCH_CMPXCHG    1
-
-static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 1:
-               __asm__ __volatile__ ("casb %0,%2,%1"
-                                     : "=d" (old), "=m" (*(char *)p)
-                                     : "d" (new), "0" (old), "m" (*(char *)p));
-               break;
-       case 2:
-               __asm__ __volatile__ ("casw %0,%2,%1"
-                                     : "=d" (old), "=m" (*(short *)p)
-                                     : "d" (new), "0" (old), "m" (*(short *)p));
-               break;
-       case 4:
-               __asm__ __volatile__ ("casl %0,%2,%1"
-                                     : "=d" (old), "=m" (*(int *)p)
-                                     : "d" (new), "0" (old), "m" (*(int *)p));
-               break;
-       }
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                                 \
-       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg_local(ptr, o, n)                                           \
-       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#else
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg.h>
-
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_SYSTEM_H */
index 74fefac00899893add2d342726fe2d2050f88cac..6b32b64bac35ffb7022d1a1cebcd7b971fc2fd3e 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/page.h>
index c73988cfa90f113383b3012111810b8f8c06cb8d..9ab4f550342e5de11c528f55781432675ffd66bf 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
index c54ef927e4836bff05b9f92b2d24b3d78b36634a..c488e3cfab53ef3356064b922d6e2d803abe3c93 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
index 149a05f8b9ee3bcf2323fa974183b8d4d25b22b5..8b4a2222e65877dd35eb736c8ca25592f8695ad0 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 
 /*
index daaa9187654ca6706278e79e5502d0a9f4f44a82..388e5cc895990ec7d7d0e838f0f1de0d78f1105d 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/traps.h>
 #include <asm/pgalloc.h>
index 147b03fbc71e533ea6d88f966a5b4a605e93106f..322c977bb9ecfbeedf470f9cfda1ed5f9ca54a5e 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 /* assembler routines */
index f60ff5f59205c1f2285f53fd2c1ae08bae9d6d93..96fa6ed7e7995b5bbee00f1d3d6f513ccba288ad 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
index eb915551de6900d79920f549694d900c04d89ca1..5e085554ac7f2bb9f0c3a964a30f001049804f8a 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/setup.h>
 #include <asm/macintosh.h>
index 2db6099784ba33d9254772417dcce05a7ac5eb36..6b020a8461e746f6ef461b748ff865aa0f4b5ce0 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/setup.h>
 #include <asm/traps.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 
index 89f3b203814b5cc4cf51038429271cb4c27df408..f77f258dce3aca67fbfbc2e02ba33718c918903f 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
index 1e33d39ca9a029d51bcd730f59eb4f725f4cecda..345ec0d83e3d4ab825ff89afd0f4b022f0c67246 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 
 /*
index 1cc2bed4c3ddd00f746869cd6e164e6cd12ea914..568cfad3ceb8daf59034282cd8e9bf776fab1f29 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index a5dbb74fe1de289ed696dfbe100dfbcb328343bb..250b8b786f4f344e70298722340e1c07b83cc5c6 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 
index 8b3db1c587fcad15de15d585d33d66534ca4b00a..0dafa693515b880450835d9a9fe87f68c87389c2 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/dma.h>
index 1b902dbd4376d7bb4a5e6882edba77bb5384515f..e0804060501e653d39392cd98e89a0e7f9e72695 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 
index 5de924ef42ed128b78631e5096e0f85ebdac31a9..a41c09149e2353158ec8ba18530a4bfc09a301e5 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index c3fb3bdd7ed9271b563650cb16c62d904f91c3bc..b6d7d8a7a3dd52ba1188067a51393e21d129df42 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index 39c79ebcd18a9dc52614844d925f1a9f6df3ed61..6ef7a81a3b12ff1bc496207b1c653db8f3bb2ace 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 
 /*
index 44b8665443141aa4220a2571396ed91c59d48932..8c20e891e9811a6c12880ce2c57a71eb5eddee7d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rtc.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/MC68328.h>
 #if defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD)
index b15ddef1ec765e78442d8721b730649f31b78c35..c801c172b822354017151cb040e348db207f73b9 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/clocksource.h>
 #include <linux/rtc.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/MC68VZ328.h>
index 599a5949f3207d0c8720604380fda0d3b4615f6d..255fc03913e9065cf3cb9474b70cc8abf002f165 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/m68360.h>
index dd2c535543410f8b98d6c2102fe2fa07e9dd8388..4f158d551f02c43595aaa75bef572a7e717edeff 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rtc.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/MC68EZ328.h>
index 25ec673edc25a2aadb5bbf14ffec27565b9d5b89..2ed8dc305e425fe5565609fa5161a01394cdf7c3 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/irq.h>
 #include <linux/rtc.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/MC68VZ328.h>
index be936480b964811a83af2ae293d79a244442a6a0..512adb64f7dd574bbe11613ddc21fc75e80bfcf1 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/rtc.h>
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index 2b888491f29a121b9c2a605285937a453e188d69..513f9bb17b9cffe6a667b3becf25471993d0b6e5 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
index 0116d208d300c7cb996a4d11fc34481c2c2be138..94fe8016f1f08a492e774c4e9bc014cf5b7ad68a 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/rtc.h>
 
 #include <asm/errno.h>
-#include <asm/system.h>
 #include <asm/rtc.h>
 #include <asm/intersil.h>
 
index 94f81ecfe3f83f91217dc1d721402d658e204dc5..8edc510a21be663122fc285df8f624cf818d6b7b 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/setup.h>
 #include <asm/traps.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 2bcb6e4bfe54a0c11eb5639e8b1286ebd5f845d0..e92364373b07f8adc0b5ef7e48ab71c2addf9848 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <linux/string.h>
 
 /* Non blocking get character from console input device, returns -1
index fc599fad4a546542a9ce0a05f9bfe2fe7baa7160..dd306c84d36d6fb8fc57b17e431b55b1160df388 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/console.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
 #include <asm/sun3xprom.h>
index 536a04aaf22f28b9de07fda6dd9420b1b31e3b3d..1d0a724804090fd52bb025755c4c5b7b40ff0292 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/sun3x.h>
 #include <asm/sun3ints.h>
index 615f53992c654e4f78625bf8708d5d92c7c12b09..472d8bf726df41ae4e82d2b4ba320c3de3172ee9 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_MICROBLAZE_ATOMIC_H
 #define _ASM_MICROBLAZE_ATOMIC_H
 
+#include <asm/cmpxchg.h>
 #include <asm-generic/atomic.h>
 #include <asm-generic/atomic64.h>
 
diff --git a/arch/microblaze/include/asm/barrier.h b/arch/microblaze/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..df5be3e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_BARRIER_H
+#define _ASM_MICROBLAZE_BARRIER_H
+
+#define nop()                  asm volatile ("nop")
+
+#define smp_read_barrier_depends()     do {} while (0)
+#define read_barrier_depends()         do {} while (0)
+
+#define mb()                   barrier()
+#define rmb()                  mb()
+#define wmb()                  mb()
+#define set_mb(var, value)     do { var = value; mb(); } while (0)
+#define set_wmb(var, value)    do { var = value; wmb(); } while (0)
+
+#define smp_mb()               mb()
+#define smp_rmb()              rmb()
+#define smp_wmb()              wmb()
+
+#endif /* _ASM_MICROBLAZE_BARRIER_H */
diff --git a/arch/microblaze/include/asm/cmpxchg.h b/arch/microblaze/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..0094859
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _ASM_MICROBLAZE_CMPXCHG_H
+#define _ASM_MICROBLAZE_CMPXCHG_H
+
+void __bad_xchg(volatile void *ptr, int size);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                                               int size)
+{
+       unsigned long ret;
+       unsigned long flags;
+
+       switch (size) {
+       case 1:
+               local_irq_save(flags);
+               ret = *(volatile unsigned char *)ptr;
+               *(volatile unsigned char *)ptr = x;
+               local_irq_restore(flags);
+               break;
+
+       case 4:
+               local_irq_save(flags);
+               ret = *(volatile unsigned long *)ptr;
+               *(volatile unsigned long *)ptr = x;
+               local_irq_restore(flags);
+               break;
+       default:
+               __bad_xchg(ptr, size), ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg.h>
+#include <asm-generic/cmpxchg-local.h>
+
+#endif /* _ASM_MICROBLAZE_CMPXCHG_H */
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h
new file mode 100644 (file)
index 0000000..e750de1
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_EXEC_H
+#define _ASM_MICROBLAZE_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_MICROBLAZE_EXEC_H */
index 352cc2352bd5109982a879e3571d9b541d6f46a6..287c5485d286ec4336d2dcdebe7e61c2735aae3a 100644 (file)
@@ -138,6 +138,8 @@ extern unsigned long memory_start;
 extern unsigned long memory_size;
 extern unsigned long lowmem_size;
 
+extern unsigned long kernel_tlb;
+
 extern int page_is_ram(unsigned long pfn);
 
 # define phys_to_pfn(phys)     (PFN_DOWN(phys))
index 7283bfb2f7e4770b37e441d33066945fcfc53087..510a8e1c16ba604f5200987fb779da24f45b48ea 100644 (file)
@@ -125,7 +125,6 @@ struct thread_struct {
        .pgdir = swapper_pg_dir, \
 }
 
-
 /* Free all resources held by a thread. */
 extern inline void release_thread(struct task_struct *dead_task)
 {
@@ -144,6 +143,8 @@ static inline void exit_thread(void)
 
 unsigned long get_wchan(struct task_struct *p);
 
+extern void ret_from_fork(void);
+
 /* The size allocated for kernel stacks. This _must_ be a power of two! */
 # define KERNEL_STACK_SIZE     0x2000
 
@@ -166,6 +167,14 @@ unsigned long get_wchan(struct task_struct *p);
 #  define STACK_TOP    TASK_SIZE
 #  define STACK_TOP_MAX        STACK_TOP
 
+void disable_hlt(void);
+void enable_hlt(void);
+void default_idle(void);
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *of_debugfs_root;
+#endif
+
 #  endif /* __ASSEMBLY__ */
 # endif /* CONFIG_MMU */
 #endif /* _ASM_MICROBLAZE_PROCESSOR_H */
index 9f195c094731b88412fb6981c54d7e1ba724d1f6..0061aa13a340a3ca8be926a2e056b4a808e923cc 100644 (file)
@@ -20,6 +20,8 @@ extern unsigned int boot_cpuid; /* move to smp.h */
 
 extern char cmd_line[COMMAND_LINE_SIZE];
 
+extern char *klimit;
+
 void early_printk(const char *fmt, ...);
 
 int setup_early_printk(char *opt);
@@ -47,6 +49,10 @@ void machine_shutdown(void);
 void machine_halt(void);
 void machine_power_off(void);
 
+void free_init_pages(char *what, unsigned long begin, unsigned long end);
+extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
+extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
+
 #  endif/* __KERNEL__ */
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/asm/switch_to.h b/arch/microblaze/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..f45baa2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SWITCH_TO_H
+#define _ASM_MICROBLAZE_SWITCH_TO_H
+
+struct task_struct;
+struct thread_info;
+
+extern struct task_struct *_switch_to(struct thread_info *prev,
+                                       struct thread_info *next);
+
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               (last) = _switch_to(task_thread_info(prev),             \
+                                       task_thread_info(next));        \
+       } while (0)
+
+#endif /* _ASM_MICROBLAZE_SWITCH_TO_H */
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
deleted file mode 100644 (file)
index 01228d2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SYSTEM_H
-#define _ASM_MICROBLAZE_SYSTEM_H
-
-#include <asm/registers.h>
-#include <asm/setup.h>
-#include <asm/irqflags.h>
-#include <asm/cache.h>
-
-#include <asm-generic/cmpxchg.h>
-#include <asm-generic/cmpxchg-local.h>
-
-struct task_struct;
-struct thread_info;
-
-extern struct task_struct *_switch_to(struct thread_info *prev,
-                                       struct thread_info *next);
-
-#define switch_to(prev, next, last)                                    \
-       do {                                                            \
-               (last) = _switch_to(task_thread_info(prev),             \
-                                       task_thread_info(next));        \
-       } while (0)
-
-#define smp_read_barrier_depends()     do {} while (0)
-#define read_barrier_depends()         do {} while (0)
-
-#define nop()                  asm volatile ("nop")
-#define mb()                   barrier()
-#define rmb()                  mb()
-#define wmb()                  mb()
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-#define set_wmb(var, value)    do { var = value; wmb(); } while (0)
-
-#define smp_mb()               mb()
-#define smp_rmb()              rmb()
-#define smp_wmb()              wmb()
-
-void __bad_xchg(volatile void *ptr, int size);
-
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
-                                                               int size)
-{
-       unsigned long ret;
-       unsigned long flags;
-
-       switch (size) {
-       case 1:
-               local_irq_save(flags);
-               ret = *(volatile unsigned char *)ptr;
-               *(volatile unsigned char *)ptr = x;
-               local_irq_restore(flags);
-               break;
-
-       case 4:
-               local_irq_save(flags);
-               ret = *(volatile unsigned long *)ptr;
-               *(volatile unsigned long *)ptr = x;
-               local_irq_restore(flags);
-               break;
-       default:
-               __bad_xchg(ptr, size), ret = 0;
-               break;
-       }
-
-       return ret;
-}
-
-void disable_hlt(void);
-void enable_hlt(void);
-void default_idle(void);
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-
-void free_init_pages(char *what, unsigned long begin, unsigned long end);
-void free_initmem(void);
-extern char *klimit;
-extern unsigned long kernel_tlb;
-extern void ret_from_fork(void);
-
-extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
-extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
-
-#ifdef CONFIG_DEBUG_FS
-extern struct dentry *of_debugfs_root;
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_MICROBLAZE_SYSTEM_H */
index 488c1ed24e381ff379c018dd81e8092a904145e7..3a749d5e71fd465f49432a130ba165b41048ed05 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/kernel.h>
 #include <linux/compiler.h>
-#include <asm/system.h>
 #include <asm/exceptions.h>
 #include <asm/pvr.h>
 
index 49faeb429599003d0908ca4c1ebc7596e6c88e66..bb4907c828dcb4c64ba4f3f291af06046c86c8a7 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
 
index 9155f7d92669a8cdf6acb5c3c6c10c21c9ed2d00..883b92789cdf849330d3b06e29fafef9b3381b39 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/pm.h>
 #include <linux/tick.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h> /* for USER_DS macros */
 #include <asm/cacheflush.h>
index 80d314e81901a2d3b0c27240af5f6ff07c3d99f7..4a764ccb9f26a81963ac2fffb3c6f0a452d8d87f 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
index 9f79fb3bbfa08430d7d07fad8e85cd1e47d88ad8..71af974aa24acfb82403968c23cb0cbccb7bb55a 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/entry.h>
 #include <asm/cpuinfo.h>
 
-#include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/pgtable.h>
 
index cadfd5608afb8026cc3a6f50c44f0d2dbb590cb3..522defa7d41fa09a42badedf7fe675dd2fe3e9bf 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/setup.h>
 #include <asm/prom.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <linux/cnt32_to_63.h>
 
 #ifdef CONFIG_SELFMOD_TIMER
index ba034d421ec27933f54d4950a3e7d3cec2761cc2..5541ac559593477a0d1d24cc658c5a04ea16d611 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/debug_locks.h>
 
 #include <asm/exceptions.h>
-#include <asm/system.h>
 #include <asm/unwind.h>
 
 void trap_init(void)
index 52746e718dfa2c0e1f40e7954446e503ddb59952..fe9c53fafdea5ba4ed297b534d49f2b130a51c3d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 
 #include <linux/string.h>
-#include <asm/system.h>
 
 #ifdef __HAVE_ARCH_MEMCPY
 #ifndef CONFIG_OPT_LIB_FUNCTION
index ae97d2ccdc22c88da115c8fd8400ebc697d04804..c38a265846dec68c427398834e9833ceced31753 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/exceptions.h>
 
index edbbae17e8209e08833bb8acc6801c433cb1ee1f..ce30e2f91d7748c0c36eb8847390bd101192a044 100644 (file)
@@ -2457,6 +2457,7 @@ config MIPS32_COMPAT
 config COMPAT
        bool
        depends on MIPS32_COMPAT
+       select ARCH_WANT_OLD_COMPAT_IPC
        default y
 
 config SYSVIPC_COMPAT
index 260b27367347b1da080e4045f00a54fa87656754..d3a9f012aa0a57db9549d13a5d9ee26151218164 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
-#include <asm/system.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/bootinfo.h>
index b1535fe409d4b50935654cf04634ab81139c2992..c3e2b85c3b0294ef75315e683100c730ace5820a 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/module.h>
 
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/time.h>
+#include <asm/setup.h>
 
 #include <asm/octeon/octeon.h>
 
index c38b190151c466eb605d7e0d8f21ff6490b49ef2..3590ab5d97916b4bf4ed9dc5e8cfd725ef6fa8c2 100644 (file)
@@ -133,7 +133,7 @@ CONFIG_BLK_DEV_BSG=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_UNINLINE_SPIN_UNLOCK is not set
 CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
 CONFIG_INLINE_READ_UNLOCK=y
 CONFIG_INLINE_READ_UNLOCK_IRQ=y
index 7abce661b90f7826b67c587c9c6c185fa9dc4eeb..5abf4e894216ac4b683772f6b187e4e9337eb2d5 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/irq_regs.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/dec/ecc.h>
index 94d23b4a7dc3e30afb4835a617b25d6d262e9b99..44d8a87a8a689580e26989e0410a7b4d24ee02ed 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 
index 07ca5405d48d5c0c357683d31e6a7991f57ddade..ebb73c51d821e6c7fd45339686aed121668d96f4 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/addrspace.h>
 #include <asm/irq_regs.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/dec/kn02ca.h>
index 925c0525344bddaa69c6279c504f6c6659806824..43feddd5e19c307685bae54bf499793aae331b41 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/init.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/wbflush.h>
+#include <asm/barrier.h>
 
 static void wbflush_kn01(void);
 static void wbflush_kn210(void);
index 7798887a1288a7fc529e29d536287536a6dd628b..b5f08255d9c73411d2b9bc0e01653e8c3d6e1909 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 
 #include <asm/irq_cpu.h>
-#include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
index 29627fbae7ad0e7700c1a6f29a20ffb251567b77..7cf80ca2c1d2117c239ba574406c6814ecb91961 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/fw/arc/types.h>
 #include <asm/sgialib.h>
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 
 VOID
 ArcHalt(VOID)
index 1d93f81d57e78ba208d0fb5ae8fea9c058ae4a54..3f4c5cb6433e2ac4765330353207d608cb1c68ed 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/cpu-features.h>
+#include <asm/cmpxchg.h>
 #include <asm/war.h>
-#include <asm/system.h>
 
 #define ATOMIC_INIT(i)    { (i) }
 
index c0884f02d3a64ea2a7ad8b1a042a19e69a905a03..f7fdc24e972da152ddadaa526f83aaba8bcc0f8b 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASM_BARRIER_H
 #define __ASM_BARRIER_H
 
+#include <asm/addrspace.h>
+
 /*
  * read_barrier_depends - Flush all pending reads that subsequents reads
  * depend on.
index d8d1c2805ac71c7c67b4e1043d15e4e072845f78..285a41fa0b18dd0412a291805781f8d811ee82de 100644 (file)
@@ -9,6 +9,130 @@
 #define __ASM_CMPXCHG_H
 
 #include <linux/irqflags.h>
+#include <asm/war.h>
+
+static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
+{
+       __u32 retval;
+
+       smp_mb__before_llsc();
+
+       if (kernel_uses_llsc && R10000_LLSC_WAR) {
+               unsigned long dummy;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:     ll      %0, %3                  # xchg_u32      \n"
+               "       .set    mips0                                   \n"
+               "       move    %2, %z4                                 \n"
+               "       .set    mips3                                   \n"
+               "       sc      %2, %1                                  \n"
+               "       beqzl   %2, 1b                                  \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+               : "R" (*m), "Jr" (val)
+               : "memory");
+       } else if (kernel_uses_llsc) {
+               unsigned long dummy;
+
+               do {
+                       __asm__ __volatile__(
+                       "       .set    mips3                           \n"
+                       "       ll      %0, %3          # xchg_u32      \n"
+                       "       .set    mips0                           \n"
+                       "       move    %2, %z4                         \n"
+                       "       .set    mips3                           \n"
+                       "       sc      %2, %1                          \n"
+                       "       .set    mips0                           \n"
+                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+                       : "R" (*m), "Jr" (val)
+                       : "memory");
+               } while (unlikely(!dummy));
+       } else {
+               unsigned long flags;
+
+               raw_local_irq_save(flags);
+               retval = *m;
+               *m = val;
+               raw_local_irq_restore(flags);   /* implies memory barrier  */
+       }
+
+       smp_llsc_mb();
+
+       return retval;
+}
+
+#ifdef CONFIG_64BIT
+static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
+{
+       __u64 retval;
+
+       smp_mb__before_llsc();
+
+       if (kernel_uses_llsc && R10000_LLSC_WAR) {
+               unsigned long dummy;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:     lld     %0, %3                  # xchg_u64      \n"
+               "       move    %2, %z4                                 \n"
+               "       scd     %2, %1                                  \n"
+               "       beqzl   %2, 1b                                  \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+               : "R" (*m), "Jr" (val)
+               : "memory");
+       } else if (kernel_uses_llsc) {
+               unsigned long dummy;
+
+               do {
+                       __asm__ __volatile__(
+                       "       .set    mips3                           \n"
+                       "       lld     %0, %3          # xchg_u64      \n"
+                       "       move    %2, %z4                         \n"
+                       "       scd     %2, %1                          \n"
+                       "       .set    mips0                           \n"
+                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+                       : "R" (*m), "Jr" (val)
+                       : "memory");
+               } while (unlikely(!dummy));
+       } else {
+               unsigned long flags;
+
+               raw_local_irq_save(flags);
+               retval = *m;
+               *m = val;
+               raw_local_irq_restore(flags);   /* implies memory barrier  */
+       }
+
+       smp_llsc_mb();
+
+       return retval;
+}
+#else
+extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
+#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
+#endif
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32(ptr, x);
+       case 8:
+               return __xchg_u64(ptr, x);
+       }
+
+       return x;
+}
+
+#define xchg(ptr, x)                                                   \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) & ~0xc);                            \
+                                                                       \
+       ((__typeof__(*(ptr)))                                           \
+               __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));     \
+})
 
 #define __HAVE_ARCH_CMPXCHG 1
 
index 2d47da62d5a7d25dec4c4361c15e2170770158ee..f5097f65a8abae4e436588bbdc939ea4a30eaedb 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/io.h>                    /* need byte IO */
 #include <linux/spinlock.h>            /* And spinlocks */
 #include <linux/delay.h>
-#include <asm/system.h>
 
 
 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
diff --git a/arch/mips/include/asm/exec.h b/arch/mips/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c1f6afa
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* _ASM_EXEC_H */
index 59f5b55b22000baff7df5afb720c02ea0bc5d024..ba4cf0e91c8b40a1306563f57f5d124a4ff305c0 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/io.h>          /* need byte IO */
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <linux/delay.h>
-#include <asm/system.h>
 
 #define NUM_AU1000_DMA_CHANNELS        8
 
index c200102c858614d7f11ce7afd95c4ccaea6eeb03..e0308dcca1358f6f2db6161486299de11d61dde5 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
-typedef unsigned int   __kernel_mode_t;
-#if (_MIPS_SZLONG == 32)
-typedef unsigned long  __kernel_nlink_t;
-#endif
 #if (_MIPS_SZLONG == 64)
 typedef unsigned int   __kernel_nlink_t;
+#define __kernel_nlink_t __kernel_nlink_t
 #endif
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
-typedef int            __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-#if (_MIPS_SZLONG == 32)
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-#endif
-#if (_MIPS_SZLONG == 64)
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
-typedef long           __kernel_ptrdiff_t;
-#endif
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef long           __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
 
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-typedef unsigned int   __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
+typedef long           __kernel_daddr_t;
+#define __kernel_daddr_t __kernel_daddr_t
 
-typedef struct {
 #if (_MIPS_SZLONG == 32)
+typedef struct {
        long    val[2];
-#endif
-#if (_MIPS_SZLONG == 64)
-       int     val[2];
-#endif
 } __kernel_fsid_t;
+#define __kernel_fsid_t __kernel_fsid_t
+#endif
 
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
-       unsigned long *__tmp = __p->fds_bits;
-       int __i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-               case 16:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       __tmp[ 8] = 0; __tmp[ 9] = 0;
-                       __tmp[10] = 0; __tmp[11] = 0;
-                       __tmp[12] = 0; __tmp[13] = 0;
-                       __tmp[14] = 0; __tmp[15] = 0;
-                       return;
-
-               case 8:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       return;
-
-               case 4:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       return;
-               }
-       }
-       __i = __FDSET_LONGS;
-       while (__i) {
-               __i--;
-               *__tmp = 0;
-               __tmp++;
-       }
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ASM_POSIX_TYPES_H */
index c104f1039a691b6338eee30a89a6c5c0bebec9db..20e9dcf42b27461f0584f01f79cfc3c1bb385edc 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/cpu-info.h>
 #include <asm/mipsregs.h>
 #include <asm/prefetch.h>
-#include <asm/system.h>
 
 /*
  * Return current * instruction pointer ("program counter").
@@ -356,6 +355,12 @@ unsigned long get_wchan(struct task_struct *p);
 #define ARCH_HAS_PREFETCHW
 #define prefetchw(x) __builtin_prefetch((x), 1, 1)
 
+/*
+ * See Documentation/scheduler/sched-arch.txt; prevents deadlock on SMP
+ * systems.
+ */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+
 #endif
 
 #endif /* _ASM_PROCESSOR_H */
index 50511aac04e91de24f7565f515ab63f99476d1df..6dce6d8d09ab08d77042c9b89a37da65e2c82f8d 100644 (file)
@@ -5,6 +5,17 @@
 
 #ifdef  __KERNEL__
 extern void setup_early_printk(void);
+
+extern void set_handler(unsigned long offset, void *addr, unsigned long len);
+extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
+
+typedef void (*vi_handler_t)(void);
+extern void *set_vi_handler(int n, vi_handler_t addr);
+
+extern void *set_except_vector(int n, void *addr);
+extern unsigned long ebase;
+extern void per_cpu_trap_init(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* __SETUP_H */
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..5d33621
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <asm/cpu-features.h>
+#include <asm/watch.h>
+#include <asm/dsp.h>
+
+struct task_struct;
+
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern asmlinkage void *resume(void *last, void *next, void *next_ti);
+
+extern unsigned int ll_bit;
+extern struct task_struct *ll_task;
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+/*
+ * Handle the scheduler resume end of FPU affinity management.  We do this
+ * inline to try to keep the overhead down. If we have been forced to run on
+ * a "CPU" with an FPU because of a previous high level of FP computation,
+ * but did not actually use the FPU during the most recent time-slice (CU1
+ * isn't set), we undo the restriction on cpus_allowed.
+ *
+ * We're not calling set_cpus_allowed() here, because we have no need to
+ * force prompt migration - we're already switching the current CPU to a
+ * different thread.
+ */
+
+#define __mips_mt_fpaff_switch_to(prev)                                        \
+do {                                                                   \
+       struct thread_info *__prev_ti = task_thread_info(prev);         \
+                                                                       \
+       if (cpu_has_fpu &&                                              \
+           test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) &&             \
+           (!(KSTK_STATUS(prev) & ST0_CU1))) {                         \
+               clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND);          \
+               prev->cpus_allowed = prev->thread.user_cpus_allowed;    \
+       }                                                               \
+       next->thread.emulated_fp = 0;                                   \
+} while(0)
+
+#else
+#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
+#endif
+
+#define __clear_software_ll_bit()                                      \
+do {                                                                   \
+       if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)       \
+               ll_bit = 0;                                             \
+} while (0)
+
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       __mips_mt_fpaff_switch_to(prev);                                \
+       if (cpu_has_dsp)                                                \
+               __save_dsp(prev);                                       \
+       __clear_software_ll_bit();                                      \
+       (last) = resume(prev, next, task_thread_info(next));            \
+} while (0)
+
+#define finish_arch_switch(prev)                                       \
+do {                                                                   \
+       if (cpu_has_dsp)                                                \
+               __restore_dsp(current);                                 \
+       if (cpu_has_userlocal)                                          \
+               write_c0_userlocal(current_thread_info()->tp_value);    \
+       __restore_watch();                                              \
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h
deleted file mode 100644 (file)
index 6018c80..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
- * Copyright (C) 1996 by Paul M. Antoine
- * Copyright (C) 1999 Silicon Graphics
- * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.
- */
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-#include <asm/addrspace.h>
-#include <asm/barrier.h>
-#include <asm/cmpxchg.h>
-#include <asm/cpu-features.h>
-#include <asm/dsp.h>
-#include <asm/watch.h>
-#include <asm/war.h>
-
-
-/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- */
-extern asmlinkage void *resume(void *last, void *next, void *next_ti);
-
-struct task_struct;
-
-extern unsigned int ll_bit;
-extern struct task_struct *ll_task;
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-
-/*
- * Handle the scheduler resume end of FPU affinity management.  We do this
- * inline to try to keep the overhead down. If we have been forced to run on
- * a "CPU" with an FPU because of a previous high level of FP computation,
- * but did not actually use the FPU during the most recent time-slice (CU1
- * isn't set), we undo the restriction on cpus_allowed.
- *
- * We're not calling set_cpus_allowed() here, because we have no need to
- * force prompt migration - we're already switching the current CPU to a
- * different thread.
- */
-
-#define __mips_mt_fpaff_switch_to(prev)                                        \
-do {                                                                   \
-       struct thread_info *__prev_ti = task_thread_info(prev);         \
-                                                                       \
-       if (cpu_has_fpu &&                                              \
-           test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) &&             \
-           (!(KSTK_STATUS(prev) & ST0_CU1))) {                         \
-               clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND);          \
-               prev->cpus_allowed = prev->thread.user_cpus_allowed;    \
-       }                                                               \
-       next->thread.emulated_fp = 0;                                   \
-} while(0)
-
-#else
-#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
-#endif
-
-#define __clear_software_ll_bit()                                      \
-do {                                                                   \
-       if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)       \
-               ll_bit = 0;                                             \
-} while (0)
-
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       __mips_mt_fpaff_switch_to(prev);                                \
-       if (cpu_has_dsp)                                                \
-               __save_dsp(prev);                                       \
-       __clear_software_ll_bit();                                      \
-       (last) = resume(prev, next, task_thread_info(next));            \
-} while (0)
-
-#define finish_arch_switch(prev)                                       \
-do {                                                                   \
-       if (cpu_has_dsp)                                                \
-               __restore_dsp(current);                                 \
-       if (cpu_has_userlocal)                                          \
-               write_c0_userlocal(current_thread_info()->tp_value);    \
-       __restore_watch();                                              \
-} while (0)
-
-static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
-{
-       __u32 retval;
-
-       smp_mb__before_llsc();
-
-       if (kernel_uses_llsc && R10000_LLSC_WAR) {
-               unsigned long dummy;
-
-               __asm__ __volatile__(
-               "       .set    mips3                                   \n"
-               "1:     ll      %0, %3                  # xchg_u32      \n"
-               "       .set    mips0                                   \n"
-               "       move    %2, %z4                                 \n"
-               "       .set    mips3                                   \n"
-               "       sc      %2, %1                                  \n"
-               "       beqzl   %2, 1b                                  \n"
-               "       .set    mips0                                   \n"
-               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-               : "R" (*m), "Jr" (val)
-               : "memory");
-       } else if (kernel_uses_llsc) {
-               unsigned long dummy;
-
-               do {
-                       __asm__ __volatile__(
-                       "       .set    mips3                           \n"
-                       "       ll      %0, %3          # xchg_u32      \n"
-                       "       .set    mips0                           \n"
-                       "       move    %2, %z4                         \n"
-                       "       .set    mips3                           \n"
-                       "       sc      %2, %1                          \n"
-                       "       .set    mips0                           \n"
-                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-                       : "R" (*m), "Jr" (val)
-                       : "memory");
-               } while (unlikely(!dummy));
-       } else {
-               unsigned long flags;
-
-               raw_local_irq_save(flags);
-               retval = *m;
-               *m = val;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
-       }
-
-       smp_llsc_mb();
-
-       return retval;
-}
-
-#ifdef CONFIG_64BIT
-static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
-{
-       __u64 retval;
-
-       smp_mb__before_llsc();
-
-       if (kernel_uses_llsc && R10000_LLSC_WAR) {
-               unsigned long dummy;
-
-               __asm__ __volatile__(
-               "       .set    mips3                                   \n"
-               "1:     lld     %0, %3                  # xchg_u64      \n"
-               "       move    %2, %z4                                 \n"
-               "       scd     %2, %1                                  \n"
-               "       beqzl   %2, 1b                                  \n"
-               "       .set    mips0                                   \n"
-               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-               : "R" (*m), "Jr" (val)
-               : "memory");
-       } else if (kernel_uses_llsc) {
-               unsigned long dummy;
-
-               do {
-                       __asm__ __volatile__(
-                       "       .set    mips3                           \n"
-                       "       lld     %0, %3          # xchg_u64      \n"
-                       "       move    %2, %z4                         \n"
-                       "       scd     %2, %1                          \n"
-                       "       .set    mips0                           \n"
-                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-                       : "R" (*m), "Jr" (val)
-                       : "memory");
-               } while (unlikely(!dummy));
-       } else {
-               unsigned long flags;
-
-               raw_local_irq_save(flags);
-               retval = *m;
-               *m = val;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
-       }
-
-       smp_llsc_mb();
-
-       return retval;
-}
-#else
-extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
-#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
-#endif
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-       case 4:
-               return __xchg_u32(ptr, x);
-       case 8:
-               return __xchg_u64(ptr, x);
-       }
-
-       return x;
-}
-
-#define xchg(ptr, x)                                                   \
-({                                                                     \
-       BUILD_BUG_ON(sizeof(*(ptr)) & ~0xc);                            \
-                                                                       \
-       ((__typeof__(*(ptr)))                                           \
-               __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));     \
-})
-
-extern void set_handler(unsigned long offset, void *addr, unsigned long len);
-extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
-
-typedef void (*vi_handler_t)(void);
-extern void *set_vi_handler(int n, vi_handler_t addr);
-
-extern void *set_except_vector(int n, void *addr);
-extern unsigned long ebase;
-extern void per_cpu_trap_init(void);
-
-/*
- * See include/asm-ia64/system.h; prevents deadlock on SMP
- * systems.
- */
-#define __ARCH_WANT_UNLOCKED_CTXSW
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-#endif /* _ASM_SYSTEM_H */
index a409c446bf18772c629d0711d654db2656c6d78a..8808d7f82da022a7cde69f52900699c65739d3db 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/txx9/tx3927.h>
 #include <asm/addrspace.h>
-#include <asm/system.h>
 #include <asm/txx9irq.h>
 
 /* CS */
index f305ca14351b77a10977a87ad5e9ec017f0e9148..d6a18644365ac07df1a7fe5ddb1d3a1629539560 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
+#include <asm/setup.h>
 
 static char bug64hit[] __initdata =
        "reliable operation impossible!\n%s";
index 0bab464b8e33be322e64dacc1263189c71dbb1ac..5099201fb7bc9933f6b939697a5d93fc02520ea9 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/watch.h>
 #include <asm/elf.h>
 #include <asm/spram.h>
index a8a8977d58872f5973401adb691f2232937d3a73..b0662cf97ea86532a96a5688bedcbca55c981242 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 static inline void unmask_rm7k_irq(struct irq_data *d)
 {
index 38874a4b9255b918af63b94f289c60a4d41523cc..1282b9ae81c4438fa4415e645e7ec7e9e4c9693a 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 static inline void unmask_rm9k_irq(struct irq_data *d)
 {
index 7f50318061b5689d295bbafe3b7eaa71da82dea1..a5aa43d07c8ed2fca645cd865bb596eed8db177e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/ftrace.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_KGDB
index 191eb52228c415d1080c1ab7eca2fd9e9e7def7d..972263bcf403fca9491cd36628651e06f00c279a 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
-#include <asm/system.h>
 
 static inline void unmask_mips_irq(struct irq_data *d)
 {
index 29811f043399588604da9bbc00efd9f0997aa530..84d0639e4580230c78fc93207943700bc35ac007 100644 (file)
@@ -326,7 +326,7 @@ static void sp_cleanup(void)
                i = j * __NFDBITS;
                if (i >= fdt->max_fds)
                        break;
-               set = fdt->open_fds->fds_bits[j++];
+               set = fdt->open_fds[j++];
                while (set) {
                        if (set & 1) {
                                struct file * file = xchg(&fdt->fd[i], NULL);
index c23d11f6851de3116125f21cb88a73ceb9e4f5a1..7f3376b1c2197f509cd9dcd85fcbc3e7e3173842 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/mipsmtregs.h>
index 61f1cb45a1d5ff2539c251662ac5db66dd770ff9..e9a5fd7277f4fd580172a5630d604e443c60513d 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
index 7786b608d9322289ce23a83eb5205b50b57f3cb6..7c24c2973c6d2ec7d5092a57b4d447aaa935a541 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 #include <asm/reg.h>
index 32644b4a07144979be8d1466ad639787abcf795d..a3b017815eff0bc3e8e918276de132b2fc336f84 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
index a9d801dec6b03c77b0ab5a1d05fa691798f59be1..b8c18dcdd2c439999f981ee8edff808b8a06c0f5 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/vpe.h>
 #include <asm/rtlx.h>
 
index 058e964e730344dc51adc3ed9737c97d0b4fc51f..c504b212f8f3f968ede65e514cbcc96168c7c330 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
-#include <asm/system.h>
 #include <asm/prom.h>
 
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
index f8524003676ac99f06d0ebb297206dfab415edce..185ca00c4c84d53be39e2d7e98031f37b6a0d5bf 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/cpu-features.h>
 #include <asm/war.h>
 #include <asm/vdso.h>
+#include <asm/dsp.h>
 
 #include "signal-common.h"
 
index aae986613795d928fa1228331c1526f8ed9e2a56..06b5da392e243ec652ba0a2e1dd25128ac005305 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/sim.h>
 #include <asm/ucontext.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/war.h>
 #include <asm/vdso.h>
+#include <asm/dsp.h>
 
 #include "signal-common.h"
 
index ee24d814d5b91bb474ff3ff114e49f86618cdeae..ae29e894ab8d0f0cf099d28dbcc1f6cf0751e546 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
index d5e950ab852792b15c2226f193f55061719f0e20..ca673569fd2421d390fbdd33029b98110727acae 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/time.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/pmon.h>
 #include <asm/cacheflush.h>
index fe3095160655755f87fa7d0641d86b4916e3bc5a..e7e03ecf54959988e029e81783422fa0c5b78554 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
index ce9e286f0a74912560adaaa428efeaeac37d6c7d..ff17868734cf5f63922dc9c13193954396d7b212 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
index 32c1e954cd3761d4c0f6c7625440387cf011f149..9c1cce9de35fdf9ff28168a87f344b84ffc3370f 100644 (file)
@@ -38,9 +38,9 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/r4k-timer.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_MIPS_MT_SMTC
 #include <asm/mipsmtregs.h>
index 928a5a61e1a61d58cd97df79330e732e2f7fc6c8..145771c0ed7a22be5f72584bfa0675f1c1078f70 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/mipsregs.h>
index 0a42ff3ff6a111992da86c13d726501b68b6d9da..c4f75bbc0bd6160deedbb7ec127feb6e2c3bdc7f 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/hazards.h>
 #include <asm/irq.h>
index 1821d12a6410b7b01ef2ec63e2ebdfca793f721e..6af08d896e20bdfd3ffc03bd7b03c99d6e7246d1 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/r4kcache.h>
 #include <asm/hazards.h>
 
index d02765708ddb9672a8ebe787068f1709d0e8d09b..b08220c82113ccd4a30a2dceac6832e2c199fabc 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/shmparam.h>
 #include <asm/sysmips.h>
 #include <asm/uaccess.h>
+#include <asm/switch_to.h>
 
 /*
  * For historic reasons the pipe(2) syscall on MIPS has an unusual calling
index d79ae5437b5871efda13f052c5f7511ccf9587b9..cfdaaa4cffc0a28fa60b662d6eccf992396ebe58 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
index aedb8941caa536c9ed76d07292ab63d905f9f7d2..9c58bdf58f23ba2b64b34dcb09f964e7cf3f95c5 100644 (file)
@@ -85,7 +85,6 @@
 #include <asm/cop2.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
index bfa12a4f97b96e46d5339aa0bfbb96bfeed4459e..f6f91523cb1c40fdd6e6c988edffa8e8cfe42dc9 100644 (file)
@@ -49,7 +49,6 @@
 #include <asm/cpu.h>
 #include <asm/mips_mt.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/vpe.h>
 #include <asm/kspd.h>
 
index b1e7a89fb73007353e45778f8eb5c4ecd467f239..e21f0b9a586e649824fb31802bdc817b4f7b7dd1 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/pm.h>
 
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/lasat/lasat.h>
 
 #include "picvue.h"
index 3c4a8c5ba7f2d3c95809e034d5a6ea45eb6a4f4e..384a3b0091ea33e507fe063c0b8b43a5ab714823 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/uaccess.h>
 #include <asm/branch.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 
 #include <asm/fpu_emulator.h>
index 915063991f6e0fd7605f1c48114502f25dd4a94a..3c104abd8aa5ebed2c565f8a99ab64a849b84475 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/smtc.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/smtc_ipi.h>
 
index 5492c42f76507cb8d3e1c23b746f371bc10e5434..77bad3c04280c88f9a776217c36e8a9063140b8f 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
+#include <asm/setup.h>
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/mc146818-time.h>
index cf7895db0739023629992e82e425fbf74389eb95..1f9ca07f53c8f33335cb316e11d6d61733e748cf 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/r4kcache.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/war.h>
 
index 0765583d0c924f6252ccb313052c46be2d81315e..031c4c2cdf2e0144df401bcb13b3cb9fec28e2a0 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
 #include <asm/bootinfo.h>
index c97087d12d0779c2c4173564f41158417fa96406..bda8eb26ece74098ecaa49c2693ab40dd2bcb772 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/pgtable.h>
 #include <asm/r4kcache.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/war.h>
 #include <asm/cacheflush.h> /* for run_uncached() */
index a43c197ccf8c48bd02f27281cba92df44221137b..87d23cada6d6d055efd41d3bf5fc486f5ec9db1a 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
 #include <asm/bootinfo.h>
index 69ebd586d7ffbef5029b8540ae3d021135035295..c14f6dfed9958008a60daf1447b9d7013e01aa8e 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/branch.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/highmem.h>               /* For VMALLOC_END */
index 36272f7d3744dc9d1a02e046f296b625a4c740cd..cc0b626858b3d0b6e34e5e510004083ce7bfba24 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/prefetch.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/mipsregs.h>
 #include <asm/mmu_context.h>
index a6bd11fba7bf773f507130b3e90f57fe39b62904..1eb708ef75ff47cfa4ad8ff8acaca83fa5fdb1a3 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/bcache.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/sgi/ip22.h>
 #include <asm/sgi/mc.h>
index 9cca8de0054507ca3869071d6bc72dab01e13170..93d937b4b1ba6fdc01460b2b55e586fbd10dda10 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/cacheops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
 
index ae1e533a096e16b2acb76e5c25fe085ef44a7d54..8d90ff25b1235880332dec654f03fb45b7f77b56 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/cacheops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
 
index ed1fa460f84ec06b3a0c19e0fd93fd717286f7e0..a63d1ed0827fefe36520b2d21877b5bd6a6767f4 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/tlbmisc.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
index 2dc625346c40f3b40f616310479b07c6695edd02..d2572cb232db90676fb097693e6ab16185713903 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/bootinfo.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/tlbmisc.h>
 
 extern void build_tlb_refill_handler(void);
index 3d95f76c106b24838a4d85bd2f7e7eb13e18da6c..91c2499f806a25809259a0b9682667ce2d7f31d5 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/bootinfo.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 extern void build_tlb_refill_handler(void);
 
index e06370f58ef3b5eee07d527ef8d653179dc60c25..0bc485b3cd606de49e62aff00c9fe611e3a90540 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/pgtable.h>
 #include <asm/war.h>
 #include <asm/uasm.h>
+#include <asm/setup.h>
 
 /*
  * TLB load/store/modify handlers.
index 4b988b9a30d51bb373b7b34c8324a1409ec2cfe8..27a6cdb36e3787be065553f823c408e2f2601a0c 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/bootinfo.h>
 #include <asm/gt64120.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/smp-ops.h>
 #include <asm/traps.h>
index a588b5cef8d2a8bed4003ee9b0056932f81a78e0..7b13a4caeea41b6377fb9410fe1397f2dce6aef2 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/msc01_ic.h>
 #include <asm/gic.h>
 #include <asm/gcmpregs.h>
+#include <asm/setup.h>
 
 int gcmp_present = -1;
 int gic_present;
index f8ee945ee411f24717640a440c69c7df550b1734..115f5bc0600332c25291483b0d451b4d7da07f0d 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/irq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
+#include <asm/setup.h>
 #include <asm/time.h>
 #include <asm/mc146818-time.h>
 #include <asm/msc01_ic.h>
index 49a4f6cf71e537d5658eb24878ce8e89a8064995..e52bfcbce093ff53e38c75dbd4df73089272e514 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/errno.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/mipsregs.h>
 #include <asm/thread_info.h>
index c4fa2d775d8b80d7db818e74b50b07e19ea6d32a..2e6f7cab24c12fb1babd90b1e53517378e38e2a1 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/irq.h>
 
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <msp_cic_int.h>
 #include <msp_regs.h>
index 98fd0099d964becd05c7e57fd5404be50c5773f3..598b6a66b97031a92262b6db52fed6086e00e361 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <msp_cic_int.h>
 #include <msp_regs.h>
index 5bbcc47da6b96954134a514888e99fc0b132ef50..83a1c5eae3f8103c09e07fb1f3fbc2ebe000300c 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <msp_slp_int.h>
 #include <msp_regs.h>
index 25bbbf428be940917b35cd518139c072918264f0..6590812daa561a29115c819cec5399343545ffba 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/titan_dep.h>
 
 /* Hypertransport specific */
index dcc926e06fcec573a4478b2359b2218d5ca942cf..6a2754c4f10641f817576c456b11abf9f74186a2 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/pmon.h>
 
index adc171c8846f29bae0fa55e5a889b7dbc6335086..a86d5d5fceb0c81f6a129d8cc9ce58fa1c448036 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <asm/mipsregs.h>
 #include <asm/irq_cpu.h>
+#include <asm/setup.h>
 #include <irq.h>
 #include <irq-mapping.h>
 #include <gpio.h>
index 529c44a52d6460ab8d6085d36d8314f2568036d3..99d82e10000bfd493df1d232d2a7c5337e8adb31 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/irq_cpu.h>
 #include <linux/io.h>
 #include <asm/irq_regs.h>
+#include <asm/setup.h>
 #include <asm/mips-boards/generic.h>
 
 #include <asm/mach-powertv/asic_regs.h>
index 7fb97fb0931e54645c7cc5598450be3b349d11b3..fa9ae9584710087a89c98f8c984bb1b03d5b95ae 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <asm/mach-powertv/asic_regs.h>
 
index 83552288e8024fa697d11e958272fe01399666e6..1cf5abbef715685f6efba80f1f6d72e6170d9c58 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/bootinfo.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 
index 7c6db74e3fad096831499fef13744d884d03a21a..f298430cff0716d8bce3aba7f6410e72b005b86c 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <asm/mach-rc32434/irq.h>
 #include <asm/mach-rc32434/gpio.h>
index 911d3999c0c7e24a34e90d014be87a4fb6b09645..3f6ccd53c15d5bcc17c83b50701aa6f75da24146 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/sched.h>
 
 #include <asm/addrspace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/branch.h>
 #include <asm/irq_regs.h>
index 45b6694c20796de82d14a15d79c34ee52d54c55a..20363d29cb5831aea5cf5277f2234ce6f21e1615 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/reboot.h>
 #include <asm/sgialib.h>
 #include <asm/sgi/ioc.h>
index 88c684e05a3de3923b437b4f6490545591fcd0b6..0626555fd1a377eb9d5c1b200207d80ab2baf8db 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/seq_file.h>
 
 #include <asm/addrspace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/branch.h>
 #include <asm/irq_regs.h>
index 23642238c6895296dc6a311ea52ba546c2eed460..69a939ae65e42faacc698d98b310901fad476f85 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <asm/processor.h>
 #include <asm/pci/bridge.h>
index c17076108d47974f21fd9a89d40b461d9389806c..f347bc6b7954b837d077a6a79a061a64db7ab143 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/sgialib.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
index a092860d5196818b1f4942dc4070af4abdac1bdc..e7d5054de8c8cf0d1408d8b5ca31c4db96000d64 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/ip32/crime.h>
 #include <asm/ip32/mace.h>
index 9b95d80ebc6e8150f0a24dd125127e72efed26dd..1f823da4c77bca73980094d4b27a043d24cffaa8 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/addrspace.h>
 #include <asm/irq.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/wbflush.h>
 #include <asm/ip32/mace.h>
 #include <asm/ip32/crime.h>
index 09740d60e18722c9e5de6d565a62aa1dfded4ce3..215713e1f3c4a80eb250992404e91da070d11e4a 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/errno.h>
 #include <asm/irq_regs.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/bcm1480_regs.h>
index 48853ab5bcf02331919b469b8d00ced02d8f06ed..e8c4538c5f610d83040db526ceff7b2a4087b5e0 100644 (file)
@@ -53,7 +53,6 @@
 #define K_INT_PERF_CNT K_BCM1480_INT_PERF_CNT
 #endif
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #define SBPROF_TB_MAJOR 240
index 45274bd3cd8b8958643cfd7fb1750db0620ad55a..86e6e54dd15d37b953defddb068e70183bb6788b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/sb1250.h>
index 76ee045e2ce41f920b7e197e79c7edfb02ef3981..340aaf626659991494d242fc01dbdebb0efda839 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/errno.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/io.h>
 
index 79f8d70f48c9617875357a57bbdfa428a041318d..244f9427625b5873003cc92132c96a32d99663eb 100644 (file)
@@ -5,7 +5,6 @@
  */
 #include <asm/io.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/sni.h>
 
 /*
index fad2bef432cdd94ad509fe2d6b45d74ee36d3661..ae0e4ee6c61728b7a609451023e28a1302ef7c37 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
-#include <asm/system.h>
 #include <asm/vr41xx/irq.h>
 
 typedef struct irq_cascade {
index 692b4e85b7fc98475ed33b5a8f3b9efd6733aa67..9fbf5f0d1faf3499a878ff3d529103754cbc5444 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 
 #define PMU_TYPE1_BASE 0x0b0000a0UL
 #define PMU_TYPE1_SIZE 0x0eUL
index b9a8f8461262b1ce045355ce811d5a9c500b27aa..975e1841ca64704b4862c6f3579bb40a3a7ab5c3 100644 (file)
 #define _ASM_ATOMIC_H
 
 #include <asm/irqflags.h>
-
-#ifndef __ASSEMBLY__
-
-#ifdef CONFIG_SMP
-#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
-static inline
-unsigned long __xchg(volatile unsigned long *m, unsigned long val)
-{
-       unsigned long status;
-       unsigned long oldval;
-
-       asm volatile(
-               "1:     mov     %4,(_AAR,%3)    \n"
-               "       mov     (_ADR,%3),%1    \n"
-               "       mov     %5,(_ADR,%3)    \n"
-               "       mov     (_ADR,%3),%0    \n"     /* flush */
-               "       mov     (_ASR,%3),%0    \n"
-               "       or      %0,%0           \n"
-               "       bne     1b              \n"
-               : "=&r"(status), "=&r"(oldval), "=m"(*m)
-               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
-               : "memory", "cc");
-
-       return oldval;
-}
-
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                                     unsigned long old, unsigned long new)
-{
-       unsigned long status;
-       unsigned long oldval;
-
-       asm volatile(
-               "1:     mov     %4,(_AAR,%3)    \n"
-               "       mov     (_ADR,%3),%1    \n"
-               "       cmp     %5,%1           \n"
-               "       bne     2f              \n"
-               "       mov     %6,(_ADR,%3)    \n"
-               "2:     mov     (_ADR,%3),%0    \n"     /* flush */
-               "       mov     (_ASR,%3),%0    \n"
-               "       or      %0,%0           \n"
-               "       bne     1b              \n"
-               : "=&r"(status), "=&r"(oldval), "=m"(*m)
-               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
-                 "r"(old), "r"(new)
-               : "memory", "cc");
-
-       return oldval;
-}
-#else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
-#error "No SMP atomic operation support!"
-#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
-
-#else  /* CONFIG_SMP */
-
-/*
- * Emulate xchg for non-SMP MN10300
- */
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
-static inline
-unsigned long __xchg(volatile unsigned long *m, unsigned long val)
-{
-       unsigned long oldval;
-       unsigned long flags;
-
-       flags = arch_local_cli_save();
-       oldval = *m;
-       *m = val;
-       arch_local_irq_restore(flags);
-       return oldval;
-}
-
-/*
- * Emulate cmpxchg for non-SMP MN10300
- */
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                                     unsigned long old, unsigned long new)
-{
-       unsigned long oldval;
-       unsigned long flags;
-
-       flags = arch_local_cli_save();
-       oldval = *m;
-       if (oldval == old)
-               *m = new;
-       arch_local_irq_restore(flags);
-       return oldval;
-}
-
-#endif /* CONFIG_SMP */
-
-#define xchg(ptr, v)                                           \
-       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
-                                    (unsigned long)(v)))
-
-#define cmpxchg(ptr, o, n)                                     \
-       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-                                       (unsigned long)(o),     \
-                                       (unsigned long)(n)))
-
-#define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
-#define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
-
-#endif /* !__ASSEMBLY__ */
+#include <asm/cmpxchg.h>
 
 #ifndef CONFIG_SMP
 #include <asm-generic/atomic.h>
@@ -269,6 +164,8 @@ static inline void atomic_dec(atomic_t *v)
        c;                                                      \
 })
 
+#define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
+#define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
 
 /**
  * atomic_clear_mask - Atomically clear bits in memory
diff --git a/arch/mn10300/include/asm/barrier.h b/arch/mn10300/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..2bd97a5
--- /dev/null
@@ -0,0 +1,37 @@
+/* MN10300 memory barrier definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_BARRIER_H
+#define _ASM_BARRIER_H
+
+#define nop()  asm volatile ("nop")
+
+#define mb()   asm volatile ("": : :"memory")
+#define rmb()  mb()
+#define wmb()  asm volatile ("": : :"memory")
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define set_mb(var, value)  do { xchg(&var, value); } while (0)
+#else  /* CONFIG_SMP */
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define set_mb(var, value)  do { var = value;  mb(); } while (0)
+#endif /* CONFIG_SMP */
+
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#define read_barrier_depends()         do {} while (0)
+#define smp_read_barrier_depends()     do {} while (0)
+
+#endif /* _ASM_BARRIER_H */
diff --git a/arch/mn10300/include/asm/cmpxchg.h b/arch/mn10300/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..97a4aaf
--- /dev/null
@@ -0,0 +1,115 @@
+/* MN10300 Atomic xchg/cmpxchg operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+#include <asm/irqflags.h>
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+       unsigned long status;
+       unsigned long oldval;
+
+       asm volatile(
+               "1:     mov     %4,(_AAR,%3)    \n"
+               "       mov     (_ADR,%3),%1    \n"
+               "       mov     %5,(_ADR,%3)    \n"
+               "       mov     (_ADR,%3),%0    \n"     /* flush */
+               "       mov     (_ASR,%3),%0    \n"
+               "       or      %0,%0           \n"
+               "       bne     1b              \n"
+               : "=&r"(status), "=&r"(oldval), "=m"(*m)
+               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
+               : "memory", "cc");
+
+       return oldval;
+}
+
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+                                     unsigned long old, unsigned long new)
+{
+       unsigned long status;
+       unsigned long oldval;
+
+       asm volatile(
+               "1:     mov     %4,(_AAR,%3)    \n"
+               "       mov     (_ADR,%3),%1    \n"
+               "       cmp     %5,%1           \n"
+               "       bne     2f              \n"
+               "       mov     %6,(_ADR,%3)    \n"
+               "2:     mov     (_ADR,%3),%0    \n"     /* flush */
+               "       mov     (_ASR,%3),%0    \n"
+               "       or      %0,%0           \n"
+               "       bne     1b              \n"
+               : "=&r"(status), "=&r"(oldval), "=m"(*m)
+               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
+                 "r"(old), "r"(new)
+               : "memory", "cc");
+
+       return oldval;
+}
+#else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+#error "No SMP atomic operation support!"
+#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+
+#else  /* CONFIG_SMP */
+
+/*
+ * Emulate xchg for non-SMP MN10300
+ */
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+       unsigned long oldval;
+       unsigned long flags;
+
+       flags = arch_local_cli_save();
+       oldval = *m;
+       *m = val;
+       arch_local_irq_restore(flags);
+       return oldval;
+}
+
+/*
+ * Emulate cmpxchg for non-SMP MN10300
+ */
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+                                     unsigned long old, unsigned long new)
+{
+       unsigned long oldval;
+       unsigned long flags;
+
+       flags = arch_local_cli_save();
+       oldval = *m;
+       if (oldval == old)
+               *m = new;
+       arch_local_irq_restore(flags);
+       return oldval;
+}
+
+#endif /* CONFIG_SMP */
+
+#define xchg(ptr, v)                                           \
+       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
+                                    (unsigned long)(v)))
+
+#define cmpxchg(ptr, o, n)                                     \
+       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
+                                       (unsigned long)(o),     \
+                                       (unsigned long)(n)))
+
+#endif /* _ASM_CMPXCHG_H */
index 098df2e617ab22b5eec54fb885106165f202166c..10b77d4628c2c1834d158b139134a4225f253c05 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <asm/system.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 #include <linux/delay.h>
diff --git a/arch/mn10300/include/asm/exec.h b/arch/mn10300/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c74e367
--- /dev/null
@@ -0,0 +1,16 @@
+/* MN10300 process execution definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_EXEC_H */
index 56ffbc1587986d5a7dd9ded3e5541a41d4c989a9..ab506181ec3108ad98c2db77d73f01e2e2b9b134 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
 #if __GNUC__ == 4
 typedef unsigned int   __kernel_size_t;
 typedef signed int     __kernel_ssize_t;
@@ -33,105 +38,11 @@ typedef unsigned long      __kernel_size_t;
 typedef signed long    __kernel_ssize_t;
 #endif
 typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
+#define __kernel_size_t __kernel_size_t
 
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
 typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-#if defined(__KERNEL__) || defined(__USE_ALL)
-       int     val[2];
-#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
-       int     __val[2];
-#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *__p)
-{
-       unsigned long *__tmp = __p->fds_bits;
-       int __i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-               case 16:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       __tmp[ 8] = 0; __tmp[ 9] = 0;
-                       __tmp[10] = 0; __tmp[11] = 0;
-                       __tmp[12] = 0; __tmp[13] = 0;
-                       __tmp[14] = 0; __tmp[15] = 0;
-                       return;
-
-               case 8:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       return;
-
-               case 4:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       return;
-               }
-       }
-       __i = __FDSET_LONGS;
-       while (__i) {
-               __i--;
-               *__tmp = 0;
-               __tmp++;
-       }
-}
-
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ASM_POSIX_TYPES_H */
diff --git a/arch/mn10300/include/asm/switch_to.h b/arch/mn10300/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..393d311
--- /dev/null
@@ -0,0 +1,49 @@
+/* MN10300 task switching definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <asm/barrier.h>
+
+struct task_struct;
+struct thread_struct;
+
+#if !defined(CONFIG_LAZY_SAVE_FPU)
+struct fpu_state_struct;
+extern asmlinkage void fpu_save(struct fpu_state_struct *);
+#define switch_fpu(prev, next)                                         \
+       do {                                                            \
+               if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) {        \
+                       (prev)->thread.fpu_flags &= ~THREAD_HAS_FPU;    \
+                       (prev)->thread.uregs->epsw &= ~EPSW_FE;         \
+                       fpu_save(&(prev)->thread.fpu_state);            \
+               }                                                       \
+       } while (0)
+#else
+#define switch_fpu(prev, next) do {} while (0)
+#endif
+
+/* context switching is now performed out-of-line in switch_to.S */
+extern asmlinkage
+struct task_struct *__switch_to(struct thread_struct *prev,
+                               struct thread_struct *next,
+                               struct task_struct *prev_task);
+
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       switch_fpu(prev, next);                                         \
+       current->thread.wchan = (u_long) __builtin_return_address(0);   \
+       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
+       mb();                                                           \
+       current->thread.wchan = 0;                                      \
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h
deleted file mode 100644 (file)
index 94b4c5e..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* MN10300 System definitions
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <asm/cpu-regs.h>
-#include <asm/intctl-regs.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-#include <linux/atomic.h>
-
-#if !defined(CONFIG_LAZY_SAVE_FPU)
-struct fpu_state_struct;
-extern asmlinkage void fpu_save(struct fpu_state_struct *);
-#define switch_fpu(prev, next)                                         \
-       do {                                                            \
-               if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) {        \
-                       (prev)->thread.fpu_flags &= ~THREAD_HAS_FPU;    \
-                       (prev)->thread.uregs->epsw &= ~EPSW_FE;         \
-                       fpu_save(&(prev)->thread.fpu_state);            \
-               }                                                       \
-       } while (0)
-#else
-#define switch_fpu(prev, next) do {} while (0)
-#endif
-
-struct task_struct;
-struct thread_struct;
-
-extern asmlinkage
-struct task_struct *__switch_to(struct thread_struct *prev,
-                               struct thread_struct *next,
-                               struct task_struct *prev_task);
-
-/* context switching is now performed out-of-line in switch_to.S */
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       switch_fpu(prev, next);                                         \
-       current->thread.wchan = (u_long) __builtin_return_address(0);   \
-       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
-       mb();                                                           \
-       current->thread.wchan = 0;                                      \
-} while (0)
-
-#define arch_align_stack(x) (x)
-
-#define nop() asm volatile ("nop")
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * For now, "wmb()" doesn't actually do anything, as all
- * Intel CPU's follow what Intel calls a *Processor Order*,
- * in which all writes are seen in the program order even
- * outside the CPU.
- *
- * I expect future Intel CPU's to have a weaker ordering,
- * but I'd also expect them to finally get their act together
- * and add some real memory barriers if so.
- *
- * Some non intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-
-#define mb()   asm volatile ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define set_mb(var, value)  do { xchg(&var, value); } while (0)
-#else  /* CONFIG_SMP */
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#endif /* CONFIG_SMP */
-
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-#endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
-#endif /* _ASM_SYSTEM_H */
index 3e3620d9fc45eb2636aaae6e9a1d3f5e8f9762ed..8e11f9f48999e172437a925bb9713a2c9c1236c2 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/irqflags.h>
 #include <asm/thread_info.h>
 #include <asm/intctl-regs.h>
index bb5fa7df6c4425f5ea856fb5625dd8d785f78493..064fa194de2b0dfa3cd3a4c003fcc7e454944d12 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/fpu.h>
 #include <asm/elf.h>
 #include <asm/exceptions.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_LAZY_SAVE_FPU
 struct task_struct *fpu_state_owner;
index f28dc99c6f729a23ba20cd73dd1bb39d80917cda..df51242744cc4617eeca151f72a8f93601367cd9 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/nmi.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <asm/serial-regs.h>
index c859cacbb9c3bfc94008f251430b038c3744ffac..caae8cac9db100dd32a1d49cfe78d71a6129aee7 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <unit/clock.h>
index 522eb8a9b60df09fe9b768b954ed7534edf68b91..a128c57b586b5b68b6883a81ff03ec731a006b20 100644 (file)
 #include <linux/bug.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <asm/debugger.h>
index 94901c56baf189551f3719dadac80c9219070687..339cef4c82568a13ac20de767f066a6e1d95f035 100644 (file)
@@ -36,7 +36,6 @@ static const char serial_revdate[] = "2007-11-06";
 #include <linux/console.h>
 #include <linux/sysrq.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
index a45f0c7549a61c8ebaa79efb699ca9deceffb8a7..db64a7166c095850c6bf18fcadcdaa3a444859fe 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/nmi.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/intctl-regs.h>
 #include <asm/rtc-regs.h>
index cac401d37f7546c4353c9e3df6ecd747fed8063b..14707f25153b15f46e97a4ad68ca5dc521bc1984 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
index 5c0b07e610063cdf34861bc0c2fc63666f696d4d..5bd58514e739729a7fb5722b39b1704df9f6dfeb 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/tracehook.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cacheflush.h>
 #include <asm/fpu.h>
index 9e7a3209a3e1bc7297a9a9c7704cbcd46d6ae45c..33c3bd1e5c6db1b03eef5b354495bc7a628541c5 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/processor.h>
 #include <linux/console.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/smp.h>
index 72938cefc05ebd9b79cff3425798acc5bc7827fb..71f1b2faaa0b1846c473099d12e732b1ca08b73f 100644 (file)
@@ -13,9 +13,9 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/thread_info.h>
 #include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
 #include <proc/smp-regs.h>
 #include <asm/asm-offsets.h>
 #include <asm/frame.inc>
index 9242e9fcc56487d41a4c37c2019d7a4ed2614eec..910dddf65e44c4c732bdc36a17f8bd21703943ce 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/processor.h>
 #include <asm/bug.h>
index 9220a75a7b43e61bce4d622b4771f2ce33ec3945..94a9c6d53e1b890ea98d987628fad089d5fd012d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bug.h>
 #include <linux/irq.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index a66c6cdaf4424974de52cbc97583b294691e0d12..37309cdb7584094de33d29f87ab805e8b9ee0c7d 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/module.h>
 #include <asm/bitops.h>
-#include <asm/system.h>
 
 /*
  * try flipping a bit using BSET and BCLR
index 0945409a802219cb8b1d7f09ef5410941a4756c0..90f346f7392d68df68844fd24472f7d5af8b1bf9 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/hardirq.h>
index 13801824e3ee298afda7db2ee5d0613266ed6ccd..e57e5bc235628ac2dc8b3dc76fabe01f1ac7c8a1 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/gfp.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index f9bb8cb1c14ad0e044320f53efca5431927e8121..b9920b1edd5a7848180876783d39ae20f261011f 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 450f7ba3f8f2ed8aaa39cfa111782be77df2c834..4ebf117c3285079d7a4ca0d9a4cee8b311b9e16c 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/spinlock.h>
 #include <linux/quicklist.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
index 9a777498a916a3c8042dee0a3abf9ba960a122ba..3e57faf04083bc6869566d4b9dcbe7590201d2cf 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/processor.h>
 #include <asm/bug.h>
index fe6e24906ffc2c9ade3e5404ef5bdeb52026f0a5..ee6d03dbc8d8d98d7ee61d9072b4c7986ee93bf2 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 11162e6c878f6cd9fefd7ec51878cefc498e755e..dcea5a0308ae880e34ec9338884c0ed9928b797b 100644 (file)
@@ -4,6 +4,7 @@ header-y += spr_defs.h
 
 generic-y += atomic.h
 generic-y += auxvec.h
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += bug.h
 generic-y += bugs.h
@@ -19,6 +20,7 @@ generic-y += div64.h
 generic-y += dma.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ftrace.h
@@ -55,6 +57,7 @@ generic-y += sockios.h
 generic-y += statfs.h
 generic-y += stat.h
 generic-y += string.h
+generic-y += switch_to.h
 generic-y += swab.h
 generic-y += termbits.h
 generic-y += termios.h
diff --git a/arch/openrisc/include/asm/system.h b/arch/openrisc/include/asm/system.h
deleted file mode 100644 (file)
index cf65888..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- * et al.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __ASM_OPENRISC_SYSTEM_H
-#define __ASM_OPENRISC_SYSTEM_H
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-#include <asm/spr.h>
-#include <asm-generic/system.h>
-
-/* We probably need this definition, but the generic system.h provides it
- * and it's not used on our arch anyway...
- */
-/*#define nop() __asm__ __volatile__ ("l.nop"::)*/
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-#endif /* __ASM_OPENRISC_SYSTEM_H */
index e5fc788778306965c13615f90a0bccff84626402..7d618feb1b72e360b909aeed3fc3dbd469e8091e 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
index e4209af879ec23b8ebc270e3c9a344df781e1b9d..55210f37d1a3e2a74ed1a30cc8cad3e6c600231f 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/spr_defs.h>
index 3d4478f6c94292f853a5bc225f772b7e498c7546..5869e3fa5dd3ac4f9b31cd63140ac01592593ddd 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
index 6deacb6b95a454b5496f0d4e37c6d8b4fac74c45..e71781d24b0eb8c2293a46ec06a4bf68264bf8f7 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 /*
  * Copy the thread state to a regset that can be interpreted by userspace.
index bf5eba22ce9e1b6503c01c311362fe9e3fd0756b..f4d5bedc3b4f72bc92a939d0cb84b71215fbd929 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/of_platform.h>
 
 #include <asm/segment.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/types.h>
 #include <asm/setup.h>
index a2ee12948f4056d9f6d50a4e03b42818569f949c..5cce396016d0c72555c8222293790ec3aa60b271 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kallsyms.h>
 #include <asm/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 736f6b2f30af3ffa528131c64ebdcda521b7405e..79dea9740a3c8508b305b88fb6974b9b517c8383 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/pagemap.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 56b0b89624af98d70b0057272094c61a6fcceb8f..683bd4d31c7cb021080c30c73f81ecd1e878b078 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
index 4054b31e0fa9da81a6db43081842c02fc3079954..3ae56073cc3d717a8ab82b78be379d6fe52fb4e3 100644 (file)
@@ -6,7 +6,6 @@
 #define _ASM_PARISC_ATOMIC_H_
 
 #include <linux/types.h>
-#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..e77d834
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __PARISC_BARRIER_H
+#define __PARISC_BARRIER_H
+
+/*
+** This is simply the barrier() macro from linux/kernel.h but when serial.c
+** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
+** hasn't yet been included yet so it fails, thus repeating the macro here.
+**
+** PA-RISC architecture allows for weakly ordered memory accesses although
+** none of the processors use it. There is a strong ordered bit that is
+** set in the O-bit of the page directory entry. Operating systems that
+** can not tolerate out of order accesses should set this bit when mapping
+** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
+** of the processor implemented the PSW O-bit). The PCX-W ERS states that
+** the TLB O-bit is not implemented so the page directory does not need to
+** have the O-bit set when mapping pages (section 3.1). This section also
+** states that the PSW Y, Z, G, and O bits are not implemented.
+** So it looks like nothing needs to be done for parisc-linux (yet).
+** (thanks to chada for the above comment -ggg)
+**
+** The __asm__ op below simple prevents gcc/ld from reordering
+** instructions across the mb() "call".
+*/
+#define mb()           __asm__ __volatile__("":::"memory")     /* barrier() */
+#define rmb()          mb()
+#define wmb()          mb()
+#define smp_mb()       mb()
+#define smp_rmb()      mb()
+#define smp_wmb()      mb()
+#define smp_read_barrier_depends()     do { } while(0)
+#define read_barrier_depends()         do { } while(0)
+
+#define set_mb(var, value)             do { var = value; mb(); } while (0)
+
+#endif /* __PARISC_BARRIER_H */
index 7a75e984674b3136e9dc21751ab9360cba6c6808..912ee7e6a579fb6dbf04fd848a96b0e24c8cb07d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _PARISC_DELAY_H
 #define _PARISC_DELAY_H
 
-#include <asm/system.h>    /* for mfctl() */
+#include <asm/special_insns.h>    /* for mfctl() */
 #include <asm/processor.h> /* for boot_cpu_data */
 
 
index f7a18f96870347172594335092840aa10a060683..fd48ae2de9506f40d7356c50641550def2d9c1b0 100644 (file)
@@ -9,7 +9,6 @@
 #define _ASM_DMA_H
 
 #include <asm/io.h>            /* need byte IO */
-#include <asm/system.h>        
 
 #define dma_outb       outb
 #define dma_inb                inb
diff --git a/arch/parisc/include/asm/exec.h b/arch/parisc/include/asm/exec.h
new file mode 100644 (file)
index 0000000..6bb5af7
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __PARISC_EXEC_H
+#define __PARISC_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __PARISC_EXEC_H */
diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h
new file mode 100644 (file)
index 0000000..d2d11b7
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __PARISC_LDCW_H
+#define __PARISC_LDCW_H
+
+#ifndef CONFIG_PA20
+/* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
+   and GCC only guarantees 8-byte alignment for stack locals, we can't
+   be assured of 16-byte alignment for atomic lock data even if we
+   specify "__attribute ((aligned(16)))" in the type declaration.  So,
+   we use a struct containing an array of four ints for the atomic lock
+   type and dynamically select the 16-byte aligned int from the array
+   for the semaphore.  */
+
+#define __PA_LDCW_ALIGNMENT    16
+#define __ldcw_align(a) ({                                     \
+       unsigned long __ret = (unsigned long) &(a)->lock[0];    \
+       __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
+               & ~(__PA_LDCW_ALIGNMENT - 1);                   \
+       (volatile unsigned int *) __ret;                        \
+})
+#define __LDCW "ldcw"
+
+#else /*CONFIG_PA20*/
+/* From: "Jim Hull" <jim.hull of hp.com>
+   I've attached a summary of the change, but basically, for PA 2.0, as
+   long as the ",CO" (coherent operation) completer is specified, then the
+   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
+   they only require "natural" alignment (4-byte for ldcw, 8-byte for
+   ldcd). */
+
+#define __PA_LDCW_ALIGNMENT    4
+#define __ldcw_align(a) (&(a)->slock)
+#define __LDCW "ldcw,co"
+
+#endif /*!CONFIG_PA20*/
+
+/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
+#define __ldcw(a) ({                                           \
+       unsigned __ret;                                         \
+       __asm__ __volatile__(__LDCW " 0(%2),%0"                 \
+               : "=r" (__ret), "+m" (*(a)) : "r" (a));         \
+       __ret;                                                  \
+})
+
+#ifdef CONFIG_SMP
+# define __lock_aligned __attribute__((__section__(".data..lock_aligned")))
+#endif
+
+#endif /* __PARISC_LDCW_H */
index 00da29a340ba9ad352294a2d47a00cff8e3daaeb..5212b0357daf15aaf454b751b0eb146fc47b34ac 100644 (file)
  * be a little careful about namespace pollution etc.  Also, we cannot
  * assume GCC is being used.
  */
-typedef unsigned long          __kernel_ino_t;
+
 typedef unsigned short         __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short         __kernel_nlink_t;
-typedef long                   __kernel_off_t;
-typedef int                    __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short         __kernel_ipc_pid_t;
-typedef unsigned int           __kernel_uid_t;
-typedef unsigned int           __kernel_gid_t;
-typedef int                    __kernel_suseconds_t;
-typedef long                   __kernel_clock_t;
-typedef int                    __kernel_timer_t;
-typedef int                    __kernel_clockid_t;
-typedef int                    __kernel_daddr_t;
-/* Note these change from narrow to wide kernels */
-#ifdef CONFIG_64BIT
-typedef unsigned long          __kernel_size_t;
-typedef long                   __kernel_ssize_t;
-typedef long                   __kernel_ptrdiff_t;
-#else
-typedef unsigned int           __kernel_size_t;
-typedef int                    __kernel_ssize_t;
-typedef int                    __kernel_ptrdiff_t;
-#endif
-typedef long                   __kernel_time_t;
-typedef char *                 __kernel_caddr_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
 
-typedef unsigned short         __kernel_uid16_t;
-typedef unsigned short         __kernel_gid16_t;
-typedef unsigned int           __kernel_uid32_t;
-typedef unsigned int           __kernel_gid32_t;
+typedef int                    __kernel_suseconds_t;
+#define __kernel_suseconds_t __kernel_suseconds_t
 
-#ifdef __GNUC__
-typedef long long              __kernel_loff_t;
 typedef long long              __kernel_off64_t;
 typedef unsigned long long     __kernel_ino64_t;
-#endif
-
-typedef unsigned int           __kernel_old_dev_t;
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-/* compatibility stuff */
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{ 
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
-       unsigned long *__tmp = __p->fds_bits;
-       int __i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-               case 16:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       __tmp[ 8] = 0; __tmp[ 9] = 0;
-                       __tmp[10] = 0; __tmp[11] = 0;
-                       __tmp[12] = 0; __tmp[13] = 0;
-                       __tmp[14] = 0; __tmp[15] = 0;
-                       return;
-
-               case 8:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       return;
-
-               case 4:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       return;
-               }
-       }
-       __i = __FDSET_LONGS;
-       while (__i) {
-               __i--;
-               *__tmp = 0;
-               __tmp++;
-       }
-}
 
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif
index 7213ec9e594cd4de25b912c17693dca742f46192..acdf4cad6125ae78203c60ce06337e6a9e0354cb 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/pdc.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
-#include <asm/system.h>
 #include <asm/percpu.h>
 
 #endif /* __ASSEMBLY__ */
@@ -169,6 +168,7 @@ struct thread_struct {
  * Return saved PC of a blocked thread.  This is used by ps mostly.
  */
 
+struct task_struct;
 unsigned long thread_saved_pc(struct task_struct *t);
 void show_trace(struct task_struct *task, unsigned long *stack);
 
index 5a3e23c9ce639591549febc256f390363553fbcf..ad69a35e9c0f76c6496f145f54096e49bb769f18 100644 (file)
 #define USER_PSW_MASK (WIDE_PSW | PSW_T | PSW_N | PSW_X | PSW_B | PSW_V | PSW_CB)
 #define USER_PSW      (PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I)
 
+#ifndef __ASSEMBLY__
+
+/* The program status word as bitfields.  */
+struct pa_psw {
+       unsigned int y:1;
+       unsigned int z:1;
+       unsigned int rv:2;
+       unsigned int w:1;
+       unsigned int e:1;
+       unsigned int s:1;
+       unsigned int t:1;
+
+       unsigned int h:1;
+       unsigned int l:1;
+       unsigned int n:1;
+       unsigned int x:1;
+       unsigned int b:1;
+       unsigned int c:1;
+       unsigned int v:1;
+       unsigned int m:1;
+
+       unsigned int cb:8;
+
+       unsigned int o:1;
+       unsigned int g:1;
+       unsigned int f:1;
+       unsigned int r:1;
+       unsigned int q:1;
+       unsigned int p:1;
+       unsigned int d:1;
+       unsigned int i:1;
+};
+
+#ifdef CONFIG_64BIT
+#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW + 4))
+#else
+#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW))
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
 #endif
diff --git a/arch/parisc/include/asm/special_insns.h b/arch/parisc/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..d306b75
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __PARISC_SPECIAL_INSNS_H
+#define __PARISC_SPECIAL_INSNS_H
+
+#define mfctl(reg)     ({              \
+       unsigned long cr;               \
+       __asm__ __volatile__(           \
+               "mfctl " #reg ",%0" :   \
+                "=r" (cr)              \
+       );                              \
+       cr;                             \
+})
+
+#define mtctl(gr, cr) \
+       __asm__ __volatile__("mtctl %0,%1" \
+               : /* no outputs */ \
+               : "r" (gr), "i" (cr) : "memory")
+
+/* these are here to de-mystefy the calling code, and to provide hooks */
+/* which I needed for debugging EIEM problems -PB */
+#define get_eiem() mfctl(15)
+static inline void set_eiem(unsigned long val)
+{
+       mtctl(val, 15);
+}
+
+#define mfsp(reg)      ({              \
+       unsigned long cr;               \
+       __asm__ __volatile__(           \
+               "mfsp " #reg ",%0" :    \
+                "=r" (cr)              \
+       );                              \
+       cr;                             \
+})
+
+#define mtsp(gr, cr) \
+       __asm__ __volatile__("mtsp %0,%1" \
+               : /* no outputs */ \
+               : "r" (gr), "i" (cr) : "memory")
+
+#endif /* __PARISC_SPECIAL_INSNS_H */
index 74036f436a3b51e9f6c6f1b55ba1f56502aa07f7..804aa28ab1d689fbf47c4a76f128d6c83072cdc5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SPINLOCK_H
 #define __ASM_SPINLOCK_H
 
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/spinlock_types.h>
 
diff --git a/arch/parisc/include/asm/switch_to.h b/arch/parisc/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..8ed8fea
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __PARISC_SWITCH_TO_H
+#define __PARISC_SWITCH_TO_H
+
+struct task_struct;
+
+extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *);
+
+#define switch_to(prev, next, last) do {                       \
+       (last) = _switch_to(prev, next);                        \
+} while(0)
+
+#endif /* __PARISC_SWITCH_TO_H */
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
deleted file mode 100644 (file)
index b19e63a..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-#ifndef __PARISC_SYSTEM_H
-#define __PARISC_SYSTEM_H
-
-#include <linux/irqflags.h>
-
-/* The program status word as bitfields.  */
-struct pa_psw {
-       unsigned int y:1;
-       unsigned int z:1;
-       unsigned int rv:2;
-       unsigned int w:1;
-       unsigned int e:1;
-       unsigned int s:1;
-       unsigned int t:1;
-
-       unsigned int h:1;
-       unsigned int l:1;
-       unsigned int n:1;
-       unsigned int x:1;
-       unsigned int b:1;
-       unsigned int c:1;
-       unsigned int v:1;
-       unsigned int m:1;
-
-       unsigned int cb:8;
-
-       unsigned int o:1;
-       unsigned int g:1;
-       unsigned int f:1;
-       unsigned int r:1;
-       unsigned int q:1;
-       unsigned int p:1;
-       unsigned int d:1;
-       unsigned int i:1;
-};
-
-#ifdef CONFIG_64BIT
-#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW + 4))
-#else
-#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW))
-#endif
-
-struct task_struct;
-
-extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *);
-
-#define switch_to(prev, next, last) do {                       \
-       (last) = _switch_to(prev, next);                        \
-} while(0)
-
-#define mfctl(reg)     ({              \
-       unsigned long cr;               \
-       __asm__ __volatile__(           \
-               "mfctl " #reg ",%0" :   \
-                "=r" (cr)              \
-       );                              \
-       cr;                             \
-})
-
-#define mtctl(gr, cr) \
-       __asm__ __volatile__("mtctl %0,%1" \
-               : /* no outputs */ \
-               : "r" (gr), "i" (cr) : "memory")
-
-/* these are here to de-mystefy the calling code, and to provide hooks */
-/* which I needed for debugging EIEM problems -PB */
-#define get_eiem() mfctl(15)
-static inline void set_eiem(unsigned long val)
-{
-       mtctl(val, 15);
-}
-
-#define mfsp(reg)      ({              \
-       unsigned long cr;               \
-       __asm__ __volatile__(           \
-               "mfsp " #reg ",%0" :    \
-                "=r" (cr)              \
-       );                              \
-       cr;                             \
-})
-
-#define mtsp(gr, cr) \
-       __asm__ __volatile__("mtsp %0,%1" \
-               : /* no outputs */ \
-               : "r" (gr), "i" (cr) : "memory")
-
-
-/*
-** This is simply the barrier() macro from linux/kernel.h but when serial.c
-** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
-** hasn't yet been included yet so it fails, thus repeating the macro here.
-**
-** PA-RISC architecture allows for weakly ordered memory accesses although
-** none of the processors use it. There is a strong ordered bit that is
-** set in the O-bit of the page directory entry. Operating systems that
-** can not tolerate out of order accesses should set this bit when mapping
-** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
-** of the processor implemented the PSW O-bit). The PCX-W ERS states that
-** the TLB O-bit is not implemented so the page directory does not need to
-** have the O-bit set when mapping pages (section 3.1). This section also
-** states that the PSW Y, Z, G, and O bits are not implemented.
-** So it looks like nothing needs to be done for parisc-linux (yet).
-** (thanks to chada for the above comment -ggg)
-**
-** The __asm__ op below simple prevents gcc/ld from reordering
-** instructions across the mb() "call".
-*/
-#define mb()           __asm__ __volatile__("":::"memory")     /* barrier() */
-#define rmb()          mb()
-#define wmb()          mb()
-#define smp_mb()       mb()
-#define smp_rmb()      mb()
-#define smp_wmb()      mb()
-#define smp_read_barrier_depends()     do { } while(0)
-#define read_barrier_depends()         do { } while(0)
-
-#define set_mb(var, value)             do { var = value; mb(); } while (0)
-
-#ifndef CONFIG_PA20
-/* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
-   and GCC only guarantees 8-byte alignment for stack locals, we can't
-   be assured of 16-byte alignment for atomic lock data even if we
-   specify "__attribute ((aligned(16)))" in the type declaration.  So,
-   we use a struct containing an array of four ints for the atomic lock
-   type and dynamically select the 16-byte aligned int from the array
-   for the semaphore.  */
-
-#define __PA_LDCW_ALIGNMENT    16
-#define __ldcw_align(a) ({                                     \
-       unsigned long __ret = (unsigned long) &(a)->lock[0];    \
-       __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
-               & ~(__PA_LDCW_ALIGNMENT - 1);                   \
-       (volatile unsigned int *) __ret;                        \
-})
-#define __LDCW "ldcw"
-
-#else /*CONFIG_PA20*/
-/* From: "Jim Hull" <jim.hull of hp.com>
-   I've attached a summary of the change, but basically, for PA 2.0, as
-   long as the ",CO" (coherent operation) completer is specified, then the
-   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
-   they only require "natural" alignment (4-byte for ldcw, 8-byte for
-   ldcd). */
-
-#define __PA_LDCW_ALIGNMENT    4
-#define __ldcw_align(a) (&(a)->slock)
-#define __LDCW "ldcw,co"
-
-#endif /*!CONFIG_PA20*/
-
-/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
-#define __ldcw(a) ({                                           \
-       unsigned __ret;                                         \
-       __asm__ __volatile__(__LDCW " 0(%2),%0"                 \
-               : "=r" (__ret), "+m" (*(a)) : "r" (a));         \
-       __ret;                                                  \
-})
-
-#ifdef CONFIG_SMP
-# define __lock_aligned __attribute__((__section__(".data..lock_aligned")))
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif
index 6d9c7c7973d0375d1c7858736c19b855e6cbb37a..83ae7dd4d99ea721adbdc16a751435db902da354 100644 (file)
@@ -5,6 +5,7 @@
 
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
+#include <asm/special_insns.h>
 
 struct thread_info {
        struct task_struct *task;       /* main task structure */
index 3b68d77273d95fecf695ca213e73908f1b1ba278..2bd51f6d832bb3f329bf23d019613e0c84face09 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASMPARISC_TIMEX_H
 #define _ASMPARISC_TIMEX_H
 
-#include <asm/system.h>
 
 #define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
 
index ff4cf9dab8d226a74ce360c4a1ac7b91265ae96b..9ac066086f030fc4080ea24be0d557afd7c8aae8 100644 (file)
@@ -5,7 +5,6 @@
  * User space memory access functions
  */
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm-generic/uaccess-unaligned.h>
index 83335f3da5fc81d8327c46ed1d90e72e2d46fc2f..9d181890a7e3cbe9b28238be7bee8e7c1c2e3e36 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/cache.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
index 4896ed0905853ddf809d1db3f2d7bf9d581eb53f..f65fa480c905fd4d06052da6afd01029a3202a5a 100644 (file)
@@ -67,7 +67,6 @@
 #include <asm/page.h>
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
-#include <asm/system.h>
 #include <asm/processor.h>     /* for boot_cpu_data */
 
 static DEFINE_SPINLOCK(pdc_lock);
index 74d544b1cd224f1fc1967b0ca84f25b49dcc380f..24644aca10cb3ab8729b1c9fb56d1b6723fc5f29 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/superio.h>
 
 #define DEBUG_RESOURCES 0
index 2905b1f52d30b0c135b8794444473830acf2b620..857c2f545470522bb51345dfaacb4f31e971113e 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/asm-offsets.h>
 
index 32d588488f04b380fb39b4b237d047fa8cc64fc1..5006e8ea305183eb5998d6f273cd3ad15dd2df7c 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/bitops.h>
 #include <linux/ftrace.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/delay.h>
index f19e6604026a870461742f6e9b1add327626342b..45ba99f5080ba2c4fb5b7105510fd4977ac47ac4 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bug.h>
 
 #include <asm/assembly.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index a8bffd8af77d36e208567365de011bc27ba30976..187118841af193adf92025351bad2d29b253c38c 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 
 #ifdef CONFIG_SMP
index d219ebecabf0b5139242f1b6fc870216ee4625d9..feab3bad6d0f265ca51c5b88c50f073d20f29e93 100644 (file)
@@ -133,7 +133,6 @@ config PPC
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
        select SPARSE_IRQ
        select IRQ_PER_CPU
        select IRQ_DOMAIN
@@ -154,6 +153,7 @@ config COMPAT
        bool
        default y if PPC64
        select COMPAT_BINFMT_ELF
+       select ARCH_WANT_OLD_COMPAT_IPC
 
 config SYSVIPC_COMPAT
        bool
index 72d55dbc6119d6b4370d6b79df8b223799934b70..e5f26890a69e01e5a5f1c4a3008f9abb49060879 100644 (file)
@@ -114,16 +114,6 @@ config DEBUGGER
        depends on KGDB || XMON
        default y
 
-config VIRQ_DEBUG
-       bool "Expose hardware/virtual IRQ mapping via debugfs"
-       depends on DEBUG_FS
-       help
-         This option will show the mapping relationship between hardware irq
-         numbers and virtual irq numbers. The mapping is exposed via debugfs
-         in the file powerpc/virq_mapping.
-
-         If you don't know what this means you don't need it.
-
 config BDI_SWITCH
        bool "Include BDI-2000 user context switcher"
        depends on DEBUG_KERNEL && PPC32
index 12da77ec0228c419b8611675a6ddfce282cede81..1c1aadc8c48fabcd3da59676a318ff393fefa9b0 100644 (file)
@@ -27,7 +27,6 @@ zImage.bin.*
 zImage.chrp
 zImage.coff
 zImage.holly
-zImage.iseries
 zImage.*lds
 zImage.miboot
 zImage.pmac
index c091aaf7685f60efce4d72d989e2503ab3a11310..f4337bacd0e7c2692396954a5f51a4ba02e1416b 100644 (file)
@@ -165,7 +165,7 @@ CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index acf7fb280464cf2f831bdbbf15df4e1d8f643a5b..f104ccde6b535903a2b4c7aa40137a4894167372 100644 (file)
@@ -279,7 +279,7 @@ CONFIG_FTRACE_SYSCALLS=y
 CONFIG_PPC_EMULATED_STATS=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_PPC_EARLY_DEBUG=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
 CONFIG_CRYPTO_NULL=m
index 7ed8d4cf2719bc9ad7a5238f4781519d3e3eee8c..82b13bfcf3c0bc1cb5fc57f2caf1237aa4445580 100644 (file)
@@ -95,7 +95,7 @@ CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index 5fb0c8a948112478ed410271a626ca3c80de2388..cc87a8441566d663071aa6b2fff7d105fc796a60 100644 (file)
@@ -214,7 +214,7 @@ CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index fb51bc90edd267bcd2270d347f6774b12d548716..48d6682f2434bfcc3ea0cbe70eb847e62de92d45 100644 (file)
@@ -216,7 +216,7 @@ CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index 1acf65026773a6b6336d21e5b3b07f06bf6e84a7..c1442a3758aea9646e16de371d44a919059ddfd4 100644 (file)
@@ -457,7 +457,7 @@ CONFIG_CODE_PATCHING_SELFTEST=y
 CONFIG_FTR_FIXUP_SELFTEST=y
 CONFIG_MSI_BITMAP_SELFTEST=y
 CONFIG_XMON=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_BOOTX_TEXT=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
index 30e7d0d20e495af21697f31fd0bd3b3114cac49c..6608232663cb1978b39c431621c77a89c9aec6d0 100644 (file)
@@ -340,7 +340,7 @@ CONFIG_FTR_FIXUP_SELFTEST=y
 CONFIG_MSI_BITMAP_SELFTEST=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
-CONFIG_VIRQ_DEBUG=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
index 14174e838ad9c443c5b68e71ebb1195a701d9c7b..da29032ae38fd312a8d9bc744a5450a3363c4763 100644 (file)
@@ -5,13 +5,9 @@
  * PowerPC atomic operations
  */
 
-#include <linux/types.h>
-
 #ifdef __KERNEL__
-#include <linux/compiler.h>
-#include <asm/synch.h>
-#include <asm/asm-compat.h>
-#include <asm/system.h>
+#include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 
index 19a099b62cd6aae4100129e52bfa1679e0bba9e8..ce17d2c9eb4ecc2549330a0a08c606d087151263 100644 (file)
@@ -16,4 +16,6 @@
  */
 #define AT_SYSINFO_EHDR                33
 
+#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
+
 #endif
diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..ae78225
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_BARRIER_H
+#define _ASM_POWERPC_BARRIER_H
+
+/*
+ * Memory barrier.
+ * The sync instruction guarantees that all memory accesses initiated
+ * by this processor have been performed (with respect to all other
+ * mechanisms that access memory).  The eieio instruction is a barrier
+ * providing an ordering (separately) for (a) cacheable stores and (b)
+ * loads and stores to non-cacheable memory (e.g. I/O devices).
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ * read_barrier_depends() prevents data-dependent loads being reordered
+ *     across this point (nop on PPC).
+ *
+ * *mb() variants without smp_ prefix must order all types of memory
+ * operations with one another. sync is the only instruction sufficient
+ * to do this.
+ *
+ * For the smp_ barriers, ordering is for cacheable memory operations
+ * only. We have to use the sync instruction for smp_mb(), since lwsync
+ * doesn't order loads with respect to previous stores.  Lwsync can be
+ * used for smp_rmb() and smp_wmb().
+ *
+ * However, on CPUs that don't support lwsync, lwsync actually maps to a
+ * heavy-weight sync, so smp_wmb() can be a lighter-weight eieio.
+ */
+#define mb()   __asm__ __volatile__ ("sync" : : : "memory")
+#define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
+#define wmb()  __asm__ __volatile__ ("sync" : : : "memory")
+#define read_barrier_depends()  do { } while(0)
+
+#define set_mb(var, value)     do { var = value; mb(); } while (0)
+
+#ifdef CONFIG_SMP
+
+#ifdef __SUBARCH_HAS_LWSYNC
+#    define SMPWMB      LWSYNC
+#else
+#    define SMPWMB      eieio
+#endif
+
+#define smp_mb()       mb()
+#define smp_rmb()      __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+#define smp_wmb()      __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif /* CONFIG_SMP */
+
+/*
+ * This is a barrier which prevents following instructions from being
+ * started until the value of the argument x is known.  For example, if
+ * x is a variable loaded from memory, this prevents following
+ * instructions from being executed until the load has been performed.
+ */
+#define data_barrier(x)        \
+       asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
+
+#endif /* _ASM_POWERPC_BARRIER_H */
index 065c590c991d2c5ddbb64c2a99d8bfc0967313da..3eb53d741070d69fe3505b694d04b8a40303a71e 100644 (file)
 
 #include <asm-generic/bug.h>
 
+#ifndef __ASSEMBLY__
+
+struct pt_regs;
+extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
+extern void bad_page_fault(struct pt_regs *, unsigned long, int);
+extern void _exception(int, struct pt_regs *, int, unsigned long);
+extern void die(const char *, struct pt_regs *, long);
+extern void print_backtrace(unsigned long *);
+
+#endif /* !__ASSEMBLY__ */
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_BUG_H */
index 4b509411ad8afcf52cf1ea5beca482b9fc282d22..9e495c9a6a889d68bca11e1575ee82c3422b7348 100644 (file)
@@ -42,8 +42,24 @@ extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
 #if !defined(__ASSEMBLY__)
+
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
+#ifdef CONFIG_6xx
+extern long _get_L2CR(void);
+extern long _get_L3CR(void);
+extern void _set_L2CR(unsigned long);
+extern void _set_L3CR(unsigned long);
+#else
+#define _get_L2CR()    0L
+#define _get_L3CR()    0L
+#define _set_L2CR(val) do { } while(0)
+#define _set_L3CR(val) do { } while(0)
 #endif
 
+extern void cacheable_memzero(void *p, unsigned int nb);
+extern void *cacheable_memcpy(void *, const void *, unsigned int);
+
+#endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
diff --git a/arch/powerpc/include/asm/cmpxchg.h b/arch/powerpc/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..e245aab
--- /dev/null
@@ -0,0 +1,309 @@
+#ifndef _ASM_POWERPC_CMPXCHG_H_
+#define _ASM_POWERPC_CMPXCHG_H_
+
+#ifdef __KERNEL__
+#include <linux/compiler.h>
+#include <asm/synch.h>
+#include <asm/asm-compat.h>
+
+/*
+ * Atomic exchange
+ *
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+static __always_inline unsigned long
+__xchg_u32(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+       PPC_RELEASE_BARRIER
+"1:    lwarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %3,0,%2 \n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
+/*
+ * Atomic exchange
+ *
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+static __always_inline unsigned long
+__xchg_u32_local(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+"1:    lwarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %3,0,%2 \n\
+       bne-    1b"
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
+#ifdef CONFIG_PPC64
+static __always_inline unsigned long
+__xchg_u64(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+       PPC_RELEASE_BARRIER
+"1:    ldarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stdcx.  %3,0,%2 \n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__xchg_u64_local(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+"1:    ldarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stdcx.  %3,0,%2 \n\
+       bne-    1b"
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+#endif
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid xchg().
+ */
+extern void __xchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long
+__xchg(volatile void *ptr, unsigned long x, unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32(ptr, x);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __xchg_u64(ptr, x);
+#endif
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+static __always_inline unsigned long
+__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32_local(ptr, x);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __xchg_u64_local(ptr, x);
+#endif
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+#define xchg(ptr,x)                                                         \
+  ({                                                                        \
+     __typeof__(*(ptr)) _x_ = (x);                                          \
+     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
+  })
+
+#define xchg_local(ptr,x)                                                   \
+  ({                                                                        \
+     __typeof__(*(ptr)) _x_ = (x);                                          \
+     (__typeof__(*(ptr))) __xchg_local((ptr),                               \
+               (unsigned long)_x_, sizeof(*(ptr)));                         \
+  })
+
+/*
+ * Compare and exchange - if *p == old, set it to new,
+ * and return the old value of *p.
+ */
+#define __HAVE_ARCH_CMPXCHG    1
+
+static __always_inline unsigned long
+__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
+{
+       unsigned int prev;
+
+       __asm__ __volatile__ (
+       PPC_RELEASE_BARRIER
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
+       cmpw    0,%0,%3\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %4,0,%2\n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
+                       unsigned long new)
+{
+       unsigned int prev;
+
+       __asm__ __volatile__ (
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
+       cmpw    0,%0,%3\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %4,0,%2\n\
+       bne-    1b"
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
+#ifdef CONFIG_PPC64
+static __always_inline unsigned long
+__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+       PPC_RELEASE_BARRIER
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
+       cmpd    0,%0,%3\n\
+       bne-    2f\n\
+       stdcx.  %4,0,%2\n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
+                       unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
+       cmpd    0,%0,%3\n\
+       bne-    2f\n\
+       stdcx.  %4,0,%2\n\
+       bne-    1b"
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+#endif
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
+         unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+#endif
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+static __always_inline unsigned long
+__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
+         unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32_local(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64_local(ptr, old, new);
+#endif
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                              \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+
+#define cmpxchg_local(ptr, o, n)                                        \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,    \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+#ifdef CONFIG_PPC64
+#define cmpxchg64(ptr, o, n)                                           \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg((ptr), (o), (n));                                       \
+  })
+#define cmpxchg64_local(ptr, o, n)                                     \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+  })
+#else
+#include <asm-generic/cmpxchg-local.h>
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_CMPXCHG_H_ */
diff --git a/arch/powerpc/include/asm/debug.h b/arch/powerpc/include/asm/debug.h
new file mode 100644 (file)
index 0000000..716d2f0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_DEBUG_H
+#define _ASM_POWERPC_DEBUG_H
+
+struct pt_regs;
+
+extern struct dentry *powerpc_debugfs_root;
+
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+
+extern int (*__debugger)(struct pt_regs *regs);
+extern int (*__debugger_ipi)(struct pt_regs *regs);
+extern int (*__debugger_bpt)(struct pt_regs *regs);
+extern int (*__debugger_sstep)(struct pt_regs *regs);
+extern int (*__debugger_iabr_match)(struct pt_regs *regs);
+extern int (*__debugger_dabr_match)(struct pt_regs *regs);
+extern int (*__debugger_fault_handler)(struct pt_regs *regs);
+
+#define DEBUGGER_BOILERPLATE(__NAME) \
+static inline int __NAME(struct pt_regs *regs) \
+{ \
+       if (unlikely(__ ## __NAME)) \
+               return __ ## __NAME(regs); \
+       return 0; \
+}
+
+DEBUGGER_BOILERPLATE(debugger)
+DEBUGGER_BOILERPLATE(debugger_ipi)
+DEBUGGER_BOILERPLATE(debugger_bpt)
+DEBUGGER_BOILERPLATE(debugger_sstep)
+DEBUGGER_BOILERPLATE(debugger_iabr_match)
+DEBUGGER_BOILERPLATE(debugger_dabr_match)
+DEBUGGER_BOILERPLATE(debugger_fault_handler)
+
+#else
+static inline int debugger(struct pt_regs *regs) { return 0; }
+static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
+static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
+static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
+static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
+#endif
+
+extern int set_dabr(unsigned long dabr);
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+extern void do_send_trap(struct pt_regs *regs, unsigned long address,
+                        unsigned long error_code, int signal_code, int brkpt);
+#else
+extern void do_dabr(struct pt_regs *regs, unsigned long address,
+                   unsigned long error_code);
+#endif
+
+#endif /* _ASM_POWERPC_DEBUG_H */
index adadb994361053ba22389e4c73aa64e42bc0f285..f6813e919bb2128991a67835e35d0e69f0b63bcf 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/io.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 
 #ifndef MAX_DMA_CHANNELS
 #define MAX_DMA_CHANNELS       8
diff --git a/arch/powerpc/include/asm/exec.h b/arch/powerpc/include/asm/exec.h
new file mode 100644 (file)
index 0000000..8196e9c
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_EXEC_H
+#define _ASM_POWERPC_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* _ASM_POWERPC_EXEC_H */
index 80fd4d2b4a62ca6e46849703b6ff812a1b50575c..be04330af75194562e3473084fd33ec7589dd696 100644 (file)
@@ -35,7 +35,7 @@ struct arch_hw_breakpoint {
 
 #include <linux/kdebug.h>
 #include <asm/reg.h>
-#include <asm/system.h>
+#include <asm/debug.h>
 
 struct perf_event;
 struct pmu;
index edfc9803ec910520c584deb86f44ccd3c9abd120..957a83f436465e52256855730a51ef307a7f6bdf 100644 (file)
@@ -112,7 +112,6 @@ extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
                             struct dma_attrs *attrs);
 
 extern void iommu_init_early_pSeries(void);
-extern void iommu_init_early_iSeries(void);
 extern void iommu_init_early_dart(void);
 extern void iommu_init_early_pasemi(void);
 
index fe0b09dceb7d1ff97c0d6ef9c591c4189446c076..cf417e51073627ff6184f15ddd3a78f7948419c7 100644 (file)
@@ -27,12 +27,6 @@ extern atomic_t ppc_n_lost_interrupts;
 /* This number is used when no interrupt has been assigned */
 #define NO_IRQ                 (0)
 
-/* This is a special irq number to return from get_irq() to tell that
- * no interrupt happened _and_ ignore it (don't count it as bad). Some
- * platforms like iSeries rely on that.
- */
-#define NO_IRQ_IGNORE          ((unsigned int)-1)
-
 /* Total number of virq in the platform */
 #define NR_IRQS                CONFIG_NR_IRQS
 
index f7727d91ac6b91d26325fdbbae46cc9e7698cba2..b921c3f48928868a74bce5142af1a346c9a79c7f 100644 (file)
@@ -265,12 +265,9 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
-#define KVM_REG_MASK           0x001f
-#define KVM_REG_EXT_MASK       0xffe0
-#define KVM_REG_GPR            0x0000
-#define KVM_REG_FPR            0x0020
-#define KVM_REG_QPR            0x0040
-#define KVM_REG_FQPR           0x0060
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
 
 #define KVM_INTERRUPT_SET      -1U
 #define KVM_INTERRUPT_UNSET    -2U
@@ -292,4 +289,41 @@ struct kvm_allocate_rma {
        __u64 rma_size;
 };
 
+struct kvm_book3e_206_tlb_entry {
+       __u32 mas8;
+       __u32 mas1;
+       __u64 mas2;
+       __u64 mas7_3;
+};
+
+struct kvm_book3e_206_tlb_params {
+       /*
+        * For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+        *
+        * - The number of ways of TLB0 must be a power of two between 2 and
+        *   16.
+        * - TLB1 must be fully associative.
+        * - The size of TLB0 must be a multiple of the number of ways, and
+        *   the number of sets must be a power of two.
+        * - The size of TLB1 may not exceed 64 entries.
+        * - TLB0 supports 4 KiB pages.
+        * - The page sizes supported by TLB1 are as indicated by
+        *   TLB1CFG (if MMUCFG[MAVN] = 0) or TLB1PS (if MMUCFG[MAVN] = 1)
+        *   as returned by KVM_GET_SREGS.
+        * - TLB2 and TLB3 are reserved, and their entries in tlb_sizes[]
+        *   and tlb_ways[] must be zero.
+        *
+        * tlb_ways[n] = tlb_sizes[n] means the array is fully associative.
+        *
+        * KVM will adjust TLBnCFG based on the sizes configured here,
+        * though arrays greater than 2048 entries will have TLBnCFG[NENTRY]
+        * set to zero.
+        */
+       __u32 tlb_sizes[4];
+       __u32 tlb_ways[4];
+       __u32 reserved[8];
+};
+
+#define KVM_REG_PPC_HIOR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+
 #endif /* __LINUX_KVM_POWERPC_H */
index 69c7377d2071aa821fd1ff9529cafd4e49d10081..aa795ccef2942feb73f8cf7e85bda5f7b1f47ad1 100644 (file)
@@ -90,6 +90,8 @@ struct kvmppc_vcpu_book3s {
 #endif
        int context_id[SID_CONTEXTS];
 
+       bool hior_explicit;             /* HIOR is set by ioctl, not PVR */
+
        struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
        struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
        struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
@@ -119,6 +121,11 @@ extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu);
 extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte);
 extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr);
 extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu);
+extern int kvmppc_book3s_hv_page_fault(struct kvm_run *run,
+                       struct kvm_vcpu *vcpu, unsigned long addr,
+                       unsigned long status);
+extern long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr,
+                       unsigned long slb_v, unsigned long valid);
 
 extern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte);
 extern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu);
@@ -138,6 +145,21 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
 extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
+extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
+                       unsigned long *rmap, long pte_index, int realmode);
+extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+                       unsigned long pte_index);
+void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+                       unsigned long pte_index);
+extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
+                       unsigned long *nb_ret);
+extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr);
+extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel);
+extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel);
+extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
+                       struct kvm_memory_slot *memslot);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
@@ -183,7 +205,9 @@ static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
 static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 {
        if ( num < 14 ) {
-               to_svcpu(vcpu)->gpr[num] = val;
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               svcpu->gpr[num] = val;
+               svcpu_put(svcpu);
                to_book3s(vcpu)->shadow_vcpu->gpr[num] = val;
        } else
                vcpu->arch.gpr[num] = val;
@@ -191,80 +215,120 @@ static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 
 static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
 {
-       if ( num < 14 )
-               return to_svcpu(vcpu)->gpr[num];
-       else
+       if ( num < 14 ) {
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               ulong r = svcpu->gpr[num];
+               svcpu_put(svcpu);
+               return r;
+       } else
                return vcpu->arch.gpr[num];
 }
 
 static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
 {
-       to_svcpu(vcpu)->cr = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->cr = val;
+       svcpu_put(svcpu);
        to_book3s(vcpu)->shadow_vcpu->cr = val;
 }
 
 static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->cr;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       u32 r;
+       r = svcpu->cr;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val)
 {
-       to_svcpu(vcpu)->xer = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->xer = val;
        to_book3s(vcpu)->shadow_vcpu->xer = val;
+       svcpu_put(svcpu);
 }
 
 static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->xer;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       u32 r;
+       r = svcpu->xer;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
 {
-       to_svcpu(vcpu)->ctr = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->ctr = val;
+       svcpu_put(svcpu);
 }
 
 static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->ctr;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->ctr;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
 {
-       to_svcpu(vcpu)->lr = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->lr = val;
+       svcpu_put(svcpu);
 }
 
 static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->lr;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->lr;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
 {
-       to_svcpu(vcpu)->pc = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->pc = val;
+       svcpu_put(svcpu);
 }
 
 static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->pc;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->pc;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
 {
        ulong pc = kvmppc_get_pc(vcpu);
-       struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu);
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       u32 r;
 
        /* Load the instruction manually if it failed to do so in the
         * exit path */
        if (svcpu->last_inst == KVM_INST_FETCH_FAILED)
                kvmppc_ld(vcpu, &pc, sizeof(u32), &svcpu->last_inst, false);
 
-       return svcpu->last_inst;
+       r = svcpu->last_inst;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->fault_dar;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->fault_dar;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
index de604db135f529cd84866ec93e68d789ffd98891..38040ff82063c5572a35e70bde330e90386ec465 100644 (file)
 #ifndef __ASM_KVM_BOOK3S_32_H__
 #define __ASM_KVM_BOOK3S_32_H__
 
-static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu)
+static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu)
 {
        return to_book3s(vcpu)->shadow_vcpu;
 }
 
+static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
+{
+}
+
 #define PTE_SIZE       12
 #define VSID_ALL       0
 #define SR_INVALID     0x00000001      /* VSID 1 should always be unused */
index d0ac94f98f9e3a2dcca21ff90631b841e4ab5060..b0c08b142770d91ad87fddd15bf6add06911bccd 100644 (file)
 #define __ASM_KVM_BOOK3S_64_H__
 
 #ifdef CONFIG_KVM_BOOK3S_PR
-static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu)
+static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu)
 {
+       preempt_disable();
        return &get_paca()->shadow_vcpu;
 }
+
+static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
+{
+       preempt_enable();
+}
 #endif
 
 #define SPAPR_TCE_SHIFT                12
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+/* For now use fixed-size 16MB page table */
+#define HPT_ORDER      24
+#define HPT_NPTEG      (1ul << (HPT_ORDER - 7))        /* 128B per pteg */
+#define HPT_NPTE       (HPT_NPTEG << 3)                /* 8 PTEs per PTEG */
+#define HPT_HASH_MASK  (HPT_NPTEG - 1)
+#endif
+
+#define VRMA_VSID      0x1ffffffUL     /* 1TB VSID reserved for VRMA */
+
+/*
+ * We use a lock bit in HPTE dword 0 to synchronize updates and
+ * accesses to each HPTE, and another bit to indicate non-present
+ * HPTEs.
+ */
+#define HPTE_V_HVLOCK  0x40UL
+#define HPTE_V_ABSENT  0x20UL
+
+static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
+{
+       unsigned long tmp, old;
+
+       asm volatile("  ldarx   %0,0,%2\n"
+                    "  and.    %1,%0,%3\n"
+                    "  bne     2f\n"
+                    "  ori     %0,%0,%4\n"
+                    "  stdcx.  %0,0,%2\n"
+                    "  beq+    2f\n"
+                    "  li      %1,%3\n"
+                    "2:        isync"
+                    : "=&r" (tmp), "=&r" (old)
+                    : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+                    : "cc", "memory");
+       return old == 0;
+}
+
 static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
                                             unsigned long pte_index)
 {
@@ -62,4 +104,140 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
        return rb;
 }
 
+static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
+{
+       /* only handle 4k, 64k and 16M pages for now */
+       if (!(h & HPTE_V_LARGE))
+               return 1ul << 12;               /* 4k page */
+       if ((l & 0xf000) == 0x1000 && cpu_has_feature(CPU_FTR_ARCH_206))
+               return 1ul << 16;               /* 64k page */
+       if ((l & 0xff000) == 0)
+               return 1ul << 24;               /* 16M page */
+       return 0;                               /* error */
+}
+
+static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize)
+{
+       return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
+}
+
+static inline int hpte_is_writable(unsigned long ptel)
+{
+       unsigned long pp = ptel & (HPTE_R_PP0 | HPTE_R_PP);
+
+       return pp != PP_RXRX && pp != PP_RXXX;
+}
+
+static inline unsigned long hpte_make_readonly(unsigned long ptel)
+{
+       if ((ptel & HPTE_R_PP0) || (ptel & HPTE_R_PP) == PP_RWXX)
+               ptel = (ptel & ~HPTE_R_PP) | PP_RXXX;
+       else
+               ptel |= PP_RXRX;
+       return ptel;
+}
+
+static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
+{
+       unsigned int wimg = ptel & HPTE_R_WIMG;
+
+       /* Handle SAO */
+       if (wimg == (HPTE_R_W | HPTE_R_I | HPTE_R_M) &&
+           cpu_has_feature(CPU_FTR_ARCH_206))
+               wimg = HPTE_R_M;
+
+       if (!io_type)
+               return wimg == HPTE_R_M;
+
+       return (wimg & (HPTE_R_W | HPTE_R_I)) == io_type;
+}
+
+/*
+ * Lock and read a linux PTE.  If it's present and writable, atomically
+ * set dirty and referenced bits and return the PTE, otherwise return 0.
+ */
+static inline pte_t kvmppc_read_update_linux_pte(pte_t *p, int writing)
+{
+       pte_t pte, tmp;
+
+       /* wait until _PAGE_BUSY is clear then set it atomically */
+       __asm__ __volatile__ (
+               "1:     ldarx   %0,0,%3\n"
+               "       andi.   %1,%0,%4\n"
+               "       bne-    1b\n"
+               "       ori     %1,%0,%4\n"
+               "       stdcx.  %1,0,%3\n"
+               "       bne-    1b"
+               : "=&r" (pte), "=&r" (tmp), "=m" (*p)
+               : "r" (p), "i" (_PAGE_BUSY)
+               : "cc");
+
+       if (pte_present(pte)) {
+               pte = pte_mkyoung(pte);
+               if (writing && pte_write(pte))
+                       pte = pte_mkdirty(pte);
+       }
+
+       *p = pte;       /* clears _PAGE_BUSY */
+
+       return pte;
+}
+
+/* Return HPTE cache control bits corresponding to Linux pte bits */
+static inline unsigned long hpte_cache_bits(unsigned long pte_val)
+{
+#if _PAGE_NO_CACHE == HPTE_R_I && _PAGE_WRITETHRU == HPTE_R_W
+       return pte_val & (HPTE_R_W | HPTE_R_I);
+#else
+       return ((pte_val & _PAGE_NO_CACHE) ? HPTE_R_I : 0) +
+               ((pte_val & _PAGE_WRITETHRU) ? HPTE_R_W : 0);
+#endif
+}
+
+static inline bool hpte_read_permission(unsigned long pp, unsigned long key)
+{
+       if (key)
+               return PP_RWRX <= pp && pp <= PP_RXRX;
+       return 1;
+}
+
+static inline bool hpte_write_permission(unsigned long pp, unsigned long key)
+{
+       if (key)
+               return pp == PP_RWRW;
+       return pp <= PP_RWRW;
+}
+
+static inline int hpte_get_skey_perm(unsigned long hpte_r, unsigned long amr)
+{
+       unsigned long skey;
+
+       skey = ((hpte_r & HPTE_R_KEY_HI) >> 57) |
+               ((hpte_r & HPTE_R_KEY_LO) >> 9);
+       return (amr >> (62 - 2 * skey)) & 3;
+}
+
+static inline void lock_rmap(unsigned long *rmap)
+{
+       do {
+               while (test_bit(KVMPPC_RMAP_LOCK_BIT, rmap))
+                       cpu_relax();
+       } while (test_and_set_bit_lock(KVMPPC_RMAP_LOCK_BIT, rmap));
+}
+
+static inline void unlock_rmap(unsigned long *rmap)
+{
+       __clear_bit_unlock(KVMPPC_RMAP_LOCK_BIT, rmap);
+}
+
+static inline bool slot_is_aligned(struct kvm_memory_slot *memslot,
+                                  unsigned long pagesize)
+{
+       unsigned long mask = (pagesize >> PAGE_SHIFT) - 1;
+
+       if (pagesize <= PAGE_SIZE)
+               return 1;
+       return !(memslot->base_gfn & mask) && !(memslot->npages & mask);
+}
+
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
index adbfca9dd100f4d2821b30d94ab8e2591da5e059..8cd50a514271b68a5b1f83abd0a891cbeb80b18f 100644 (file)
 #define E500_PID_NUM   3
 #define E500_TLB_NUM   2
 
-struct tlbe{
-       u32 mas1;
-       u32 mas2;
-       u32 mas3;
-       u32 mas7;
-};
-
 #define E500_TLB_VALID 1
 #define E500_TLB_DIRTY 2
 
-struct tlbe_priv {
+struct tlbe_ref {
        pfn_t pfn;
        unsigned int flags; /* E500_TLB_* */
 };
 
+struct tlbe_priv {
+       struct tlbe_ref ref; /* TLB0 only -- TLB1 uses tlb_refs */
+};
+
 struct vcpu_id_table;
 
+struct kvmppc_e500_tlb_params {
+       int entries, ways, sets;
+};
+
 struct kvmppc_vcpu_e500 {
-       /* Unmodified copy of the guest's TLB. */
-       struct tlbe *gtlb_arch[E500_TLB_NUM];
+       /* Unmodified copy of the guest's TLB -- shared with host userspace. */
+       struct kvm_book3e_206_tlb_entry *gtlb_arch;
+
+       /* Starting entry number in gtlb_arch[] */
+       int gtlb_offset[E500_TLB_NUM];
 
        /* KVM internal information associated with each guest TLB entry */
        struct tlbe_priv *gtlb_priv[E500_TLB_NUM];
 
-       unsigned int gtlb_size[E500_TLB_NUM];
+       struct kvmppc_e500_tlb_params gtlb_params[E500_TLB_NUM];
+
        unsigned int gtlb_nv[E500_TLB_NUM];
 
+       /*
+        * information associated with each host TLB entry --
+        * TLB1 only for now.  If/when guest TLB1 entries can be
+        * mapped with host TLB0, this will be used for that too.
+        *
+        * We don't want to use this for guest TLB0 because then we'd
+        * have the overhead of doing the translation again even if
+        * the entry is still in the guest TLB (e.g. we swapped out
+        * and back, and our host TLB entries got evicted).
+        */
+       struct tlbe_ref *tlb_refs[E500_TLB_NUM];
+       unsigned int host_tlb1_nv;
+
        u32 host_pid[E500_PID_NUM];
        u32 pid[E500_PID_NUM];
        u32 svr;
 
-       u32 mas0;
-       u32 mas1;
-       u32 mas2;
-       u32 mas3;
-       u32 mas4;
-       u32 mas5;
-       u32 mas6;
-       u32 mas7;
-
        /* vcpu id table */
        struct vcpu_id_table *idt;
 
@@ -73,6 +82,9 @@ struct kvmppc_vcpu_e500 {
        u32 tlb1cfg;
        u64 mcar;
 
+       struct page **shared_tlb_pages;
+       int num_shared_tlb_pages;
+
        struct kvm_vcpu vcpu;
 };
 
index bf8af5d5d5dc6e6ad0a8799f69394b17c4e44300..52eb9c1f4fe01cd463523fb55b782069929bf911 100644 (file)
 #include <linux/atomic.h>
 #include <asm/kvm_asm.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 
 #define KVM_MAX_VCPUS          NR_CPUS
 #define KVM_MAX_VCORES         NR_CPUS
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
+#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
 
 #ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+#include <linux/mmu_notifier.h>
+
+#define KVM_ARCH_WANT_MMU_NOTIFIER
+
+struct kvm;
+extern int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
+extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
+
+#endif
+
 /* We don't currently support large pages. */
 #define KVM_HPAGE_GFN_SHIFT(x) 0
 #define KVM_NR_PAGE_SIZES      1
@@ -158,34 +173,72 @@ struct kvmppc_spapr_tce_table {
        struct page *pages[0];
 };
 
-struct kvmppc_rma_info {
+struct kvmppc_linear_info {
        void            *base_virt;
        unsigned long    base_pfn;
        unsigned long    npages;
        struct list_head list;
-       atomic_t         use_count;
+       atomic_t         use_count;
+       int              type;
+};
+
+/*
+ * The reverse mapping array has one entry for each HPTE,
+ * which stores the guest's view of the second word of the HPTE
+ * (including the guest physical address of the mapping),
+ * plus forward and backward pointers in a doubly-linked ring
+ * of HPTEs that map the same host page.  The pointers in this
+ * ring are 32-bit HPTE indexes, to save space.
+ */
+struct revmap_entry {
+       unsigned long guest_rpte;
+       unsigned int forw, back;
+};
+
+/*
+ * We use the top bit of each memslot->rmap entry as a lock bit,
+ * and bit 32 as a present flag.  The bottom 32 bits are the
+ * index in the guest HPT of a HPTE that points to the page.
+ */
+#define KVMPPC_RMAP_LOCK_BIT   63
+#define KVMPPC_RMAP_RC_SHIFT   32
+#define KVMPPC_RMAP_REFERENCED (HPTE_R_R << KVMPPC_RMAP_RC_SHIFT)
+#define KVMPPC_RMAP_CHANGED    (HPTE_R_C << KVMPPC_RMAP_RC_SHIFT)
+#define KVMPPC_RMAP_PRESENT    0x100000000ul
+#define KVMPPC_RMAP_INDEX      0xfffffffful
+
+/* Low-order bits in kvm->arch.slot_phys[][] */
+#define KVMPPC_PAGE_ORDER_MASK 0x1f
+#define KVMPPC_PAGE_NO_CACHE   HPTE_R_I        /* 0x20 */
+#define KVMPPC_PAGE_WRITETHRU  HPTE_R_W        /* 0x40 */
+#define KVMPPC_GOT_PAGE                0x80
+
+struct kvm_arch_memory_slot {
 };
 
 struct kvm_arch {
 #ifdef CONFIG_KVM_BOOK3S_64_HV
        unsigned long hpt_virt;
-       unsigned long ram_npages;
-       unsigned long ram_psize;
-       unsigned long ram_porder;
-       struct kvmppc_pginfo *ram_pginfo;
+       struct revmap_entry *revmap;
        unsigned int lpid;
        unsigned int host_lpid;
        unsigned long host_lpcr;
        unsigned long sdr1;
        unsigned long host_sdr1;
        int tlbie_lock;
-       int n_rma_pages;
        unsigned long lpcr;
        unsigned long rmor;
-       struct kvmppc_rma_info *rma;
+       struct kvmppc_linear_info *rma;
+       unsigned long vrma_slb_v;
+       int rma_setup_done;
+       int using_mmu_notifiers;
        struct list_head spapr_tce_tables;
+       spinlock_t slot_phys_lock;
+       unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
+       int slot_npages[KVM_MEM_SLOTS_NUM];
        unsigned short last_vcpu[NR_CPUS];
        struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+       struct kvmppc_linear_info *hpt_li;
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
@@ -318,10 +371,6 @@ struct kvm_vcpu_arch {
        u32 vrsave; /* also USPRG0 */
        u32 mmucr;
        ulong shadow_msr;
-       ulong sprg4;
-       ulong sprg5;
-       ulong sprg6;
-       ulong sprg7;
        ulong csrr0;
        ulong csrr1;
        ulong dsrr0;
@@ -329,16 +378,14 @@ struct kvm_vcpu_arch {
        ulong mcsrr0;
        ulong mcsrr1;
        ulong mcsr;
-       ulong esr;
        u32 dec;
        u32 decar;
        u32 tbl;
        u32 tbu;
        u32 tcr;
-       u32 tsr;
+       ulong tsr; /* we need to perform set/clr_bits() which requires ulong */
        u32 ivor[64];
        ulong ivpr;
-       u32 pir;
        u32 pvr;
 
        u32 shadow_pid;
@@ -427,9 +474,14 @@ struct kvm_vcpu_arch {
 #ifdef CONFIG_KVM_BOOK3S_64_HV
        struct kvm_vcpu_arch_shared shregs;
 
+       unsigned long pgfault_addr;
+       long pgfault_index;
+       unsigned long pgfault_hpte[2];
+
        struct list_head run_list;
        struct task_struct *run_task;
        struct kvm_run *kvm_run;
+       pgd_t *pgdir;
 #endif
 };
 
@@ -438,4 +490,12 @@ struct kvm_vcpu_arch {
 #define KVMPPC_VCPU_BUSY_IN_HOST       1
 #define KVMPPC_VCPU_RUNNABLE           2
 
+/* Values for vcpu->arch.io_gpr */
+#define KVM_MMIO_REG_MASK      0x001f
+#define KVM_MMIO_REG_EXT_MASK  0xffe0
+#define KVM_MMIO_REG_GPR       0x0000
+#define KVM_MMIO_REG_FPR       0x0020
+#define KVM_MMIO_REG_QPR       0x0040
+#define KVM_MMIO_REG_FQPR      0x0060
+
 #endif /* __POWERPC_KVM_HOST_H__ */
index 50533f9adf40548671c6b28473d783d950b40156..7b754e74300397e2d92f7cab4adb10ddadf1a726 100644 (file)
 
 #include <linux/types.h>
 
+/*
+ * Additions to this struct must only occur at the end, and should be
+ * accompanied by a KVM_MAGIC_FEAT flag to advertise that they are present
+ * (albeit not necessarily relevant to the current target hardware platform).
+ *
+ * Struct fields are always 32 or 64 bit aligned, depending on them being 32
+ * or 64 bit wide respectively.
+ *
+ * See Documentation/virtual/kvm/ppc-pv.txt
+ */
 struct kvm_vcpu_arch_shared {
        __u64 scratch1;
        __u64 scratch2;
@@ -33,11 +43,35 @@ struct kvm_vcpu_arch_shared {
        __u64 sprg3;
        __u64 srr0;
        __u64 srr1;
-       __u64 dar;
+       __u64 dar;              /* dear on BookE */
        __u64 msr;
        __u32 dsisr;
        __u32 int_pending;      /* Tells the guest if we have an interrupt */
        __u32 sr[16];
+       __u32 mas0;
+       __u32 mas1;
+       __u64 mas7_3;
+       __u64 mas2;
+       __u32 mas4;
+       __u32 mas6;
+       __u32 esr;
+       __u32 pir;
+
+       /*
+        * SPRG4-7 are user-readable, so we can only keep these consistent
+        * between the shared area and the real registers when there's an
+        * intervening exit to KVM.  This also applies to SPRG3 on some
+        * chips.
+        *
+        * This suffices for access by guest userspace, since in PR-mode
+        * KVM, an exit must occur when changing the guest's MSR[PR].
+        * If the guest kernel writes to SPRG3-7 via the shared area, it
+        * must also use the shared area for reading while in kernel space.
+        */
+       __u64 sprg4;
+       __u64 sprg5;
+       __u64 sprg6;
+       __u64 sprg7;
 };
 
 #define KVM_SC_MAGIC_R0                0x4b564d21 /* "KVM!" */
@@ -47,7 +81,10 @@ struct kvm_vcpu_arch_shared {
 
 #define KVM_FEATURE_MAGIC_PAGE 1
 
-#define KVM_MAGIC_FEAT_SR      (1 << 0)
+#define KVM_MAGIC_FEAT_SR              (1 << 0)
+
+/* MASn, ESR, PIR, and high SPRGs */
+#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7   (1 << 1)
 
 #ifdef __KERNEL__
 
index 46efd1a265c958775f390a4b72d53d40c8890e3a..9d6dee0f7d48ecc442b3d1e8062583c033434e69 100644 (file)
@@ -66,6 +66,7 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run,
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
+extern void kvmppc_decrementer_func(unsigned long data);
 extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
@@ -94,7 +95,7 @@ extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
 extern void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);
 
-extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags);
 extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
@@ -120,15 +121,17 @@ extern long kvmppc_alloc_hpt(struct kvm *kvm);
 extern void kvmppc_free_hpt(struct kvm *kvm);
 extern long kvmppc_prepare_vrma(struct kvm *kvm,
                                struct kvm_userspace_memory_region *mem);
-extern void kvmppc_map_vrma(struct kvm *kvm,
-                           struct kvm_userspace_memory_region *mem);
+extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
+                       struct kvm_memory_slot *memslot, unsigned long porder);
 extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
 extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
                                struct kvm_create_spapr_tce *args);
 extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
                                struct kvm_allocate_rma *rma);
-extern struct kvmppc_rma_info *kvm_alloc_rma(void);
-extern void kvm_release_rma(struct kvmppc_rma_info *ri);
+extern struct kvmppc_linear_info *kvm_alloc_rma(void);
+extern void kvm_release_rma(struct kvmppc_linear_info *ri);
+extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
+extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
@@ -175,6 +178,9 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
@@ -183,14 +189,19 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
        paca[cpu].kvm_hstate.xics_phys = addr;
 }
 
-extern void kvm_rma_init(void);
+extern void kvm_linear_init(void);
 
 #else
 static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 {}
 
-static inline void kvm_rma_init(void)
+static inline void kvm_linear_init(void)
 {}
 #endif
 
+int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
+                             struct kvm_config_tlb *cfg);
+int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
+                            struct kvm_dirty_tlb *cfg);
+
 #endif /* __POWERPC_KVM_PPC_H__ */
index bf37931d1ad6d7254f4a2e10149a040b3a059e36..42ce570812c1629afb75ed7a5a472d059570305c 100644 (file)
@@ -99,9 +99,7 @@ struct machdep_calls {
 
        void            (*init_IRQ)(void);
 
-       /* Return an irq, or NO_IRQ to indicate there are none pending.
-        * If for some reason there is no irq, but the interrupt
-        * shouldn't be counted as spurious, return NO_IRQ_IGNORE. */
+       /* Return an irq, or NO_IRQ to indicate there are none pending. */
        unsigned int    (*get_irq)(void);
 
        /* PCI stuff */
index f5f89cafebd027c115570651d6bc19f038f29746..cdb5421877e2e2259ed3265df92d655aa62dd115 100644 (file)
 /* MAS registers bit definitions */
 
 #define MAS0_TLBSEL(x)         (((x) << 28) & 0x30000000)
-#define MAS0_ESEL(x)           (((x) << 16) & 0x0FFF0000)
-#define MAS0_NV(x)             ((x) & 0x00000FFF)
 #define MAS0_ESEL_MASK         0x0FFF0000
+#define MAS0_ESEL_SHIFT                16
+#define MAS0_ESEL(x)           (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
+#define MAS0_NV(x)             ((x) & 0x00000FFF)
 #define MAS0_HES               0x00004000
 #define MAS0_WQ_ALLWAYS                0x00000000
 #define MAS0_WQ_COND           0x00001000
 #define TLBnCFG_MAXSIZE                0x000f0000      /* Maximum Page Size (v1.0) */
 #define TLBnCFG_MAXSIZE_SHIFT  16
 #define TLBnCFG_ASSOC          0xff000000      /* Associativity */
+#define TLBnCFG_ASSOC_SHIFT    24
 
 /* TLBnPS encoding */
 #define TLBnPS_4K              0x00000004
index 412ba493cb987ef82a701a6410040a175ceaa0df..1c65a59881eae6ad5fc237b12f424d47a0caddca 100644 (file)
@@ -108,11 +108,11 @@ extern char initial_stab[];
 #define HPTE_V_VRMA_MASK       ASM_CONST(0x4001ffffff000000)
 
 /* Values for PP (assumes Ks=0, Kp=1) */
-/* pp0 will always be 0 for linux     */
 #define PP_RWXX        0       /* Supervisor read/write, User none */
 #define PP_RWRX 1      /* Supervisor read/write, User read */
 #define PP_RWRW 2      /* Supervisor read/write, User read/write */
 #define PP_RXRX 3      /* Supervisor read,       User read */
+#define PP_RXXX        (HPTE_R_PP0 | 2)        /* Supervisor read, user none */
 
 #ifndef __ASSEMBLY__
 
@@ -267,7 +267,6 @@ extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void hpte_init_native(void);
 extern void hpte_init_lpar(void);
-extern void hpte_init_iSeries(void);
 extern void hpte_init_beat(void);
 extern void hpte_init_beat_v3(void);
 
@@ -325,9 +324,6 @@ extern void slb_set_size(u16 size);
  * WARNING - If you change these you must make sure the asm
  * implementations in slb_allocate (slb_low.S), do_stab_bolted
  * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
- *
- * You'll also need to change the precomputed VSID values in head.S
- * which are used by the iSeries firmware.
  */
 
 #define VSID_MULTIPLIER_256M   ASM_CONST(200730139)    /* 28-bit prime */
@@ -484,14 +480,6 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
                             | (ea >> SID_SHIFT_1T), 1T);
 }
 
-/*
- * This is only used on legacy iSeries in lparmap.c,
- * hence the 256MB segment assumption.
- */
-#define VSID_SCRAMBLE(pvsid)   (((pvsid) * VSID_MULTIPLIER_256M) %     \
-                                VSID_MODULUS_256M)
-#define KERNEL_VSID(ea)                VSID_SCRAMBLE(GET_ESID(ea))
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_MMU_HASH64_H_ */
index 5d487657322e11d38ccfd47591a264dd2e73145e..ac39e6a3b25a4346394a49db68f2238a69f1532f 100644 (file)
@@ -155,14 +155,7 @@ struct pci_dn {
 
        struct  pci_dev *pcidev;        /* back-pointer to the pci device */
 #ifdef CONFIG_EEH
-       int     class_code;             /* pci device class */
-       int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
-       int     eeh_config_addr;
-       int     eeh_pe_config_addr; /* new-style partition endpoint address */
-       int     eeh_check_count;        /* # times driver ignored error */
-       int     eeh_freeze_count;       /* # times this device froze up. */
-       int     eeh_false_positives;    /* # times this device reported #ff's */
-       u32     config_space[16];       /* saved PCI config space */
+       struct eeh_dev *edev;           /* eeh device */
 #endif
 #define IODA_INVALID_PE                (-1)
 #ifdef CONFIG_PPC_POWERNV
@@ -185,6 +178,13 @@ static inline int pci_device_from_OF_node(struct device_node *np,
        return 0;
 }
 
+#if defined(CONFIG_EEH)
+static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
+{
+       return PCI_DN(dn)->edev;
+}
+#endif
+
 /** Find the bus corresponding to the indicated device node */
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
index 1a8093fa8f711a80c6d599507dfe8e0d0a0006bb..078019b5b353c916f49dd0d71087260302569c60 100644 (file)
@@ -47,6 +47,8 @@ struct power_pmu {
  */
 #define PPMU_LIMITED_PMC5_6    1       /* PMC5/6 have limited function */
 #define PPMU_ALT_SIPR          2       /* uses alternate posn for SIPR/HV */
+#define PPMU_NO_SIPR           4       /* no SIPR/HV in MMCRA at all */
+#define PPMU_NO_CONT_SAMPLING  8       /* no continuous sampling */
 
 /*
  * Values for flags to get_alternatives()
index c4e396b540df54289c0d5b2433ec3e93608a39d2..f1393252bbdad837c97b794c8534328a9c912ee3 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
-typedef unsigned int   __kernel_mode_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-typedef long           __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef long           __kernel_suseconds_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-typedef unsigned int   __kernel_old_uid_t;
-typedef unsigned int   __kernel_old_gid_t;
-
 #ifdef __powerpc64__
-typedef unsigned long          __kernel_nlink_t;
-typedef int             __kernel_ipc_pid_t;
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
 typedef unsigned long  __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 #else
-typedef unsigned short __kernel_nlink_t;
-typedef short          __kernel_ipc_pid_t;
 typedef unsigned int   __kernel_size_t;
 typedef int            __kernel_ssize_t;
-typedef unsigned int   __kernel_old_dev_t;
-#endif
-
-#ifdef __powerpc64__
-typedef long long      __kernel_loff_t;
-#else
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#ifndef __GNUC__
-
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define        __FD_ISSET(d, set)      (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
-#define        __FD_ZERO(set)  \
-  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
-
-#else /* __GNUC__ */
-
-#if defined(__KERNEL__)
-/* With GNU C, use inline functions instead so args are evaluated only once: */
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
-{ 
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
-{
-       unsigned long *tmp = (unsigned long *)p->fds_bits;
-       int i;
+typedef long           __kernel_ptrdiff_t;
+#define __kernel_size_t __kernel_size_t
 
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-                     case 16:
-                       tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                       tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+typedef unsigned short __kernel_nlink_t;
+#define __kernel_nlink_t __kernel_nlink_t
 
-                     case 8:
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+typedef short          __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+#endif
 
-                     case 4:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       return;
-               }
-       }
-       i = __FDSET_LONGS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
+#include <asm-generic/posix_types.h>
 
-#endif /* defined(__KERNEL__) */
-#endif /* __GNUC__ */
 #endif /* _ASM_POWERPC_POSIX_TYPES_H */
index e980faae4225098d37e087d502bfb70166d9ea29..d81f99430fe75b9b7b53ebe38337ee9184091eb4 100644 (file)
@@ -45,6 +45,7 @@
 #define PPC_INST_MFSPR_DSCR_MASK       0xfc1fffff
 #define PPC_INST_MTSPR_DSCR            0x7c1103a6
 #define PPC_INST_MTSPR_DSCR_MASK       0xfc1fffff
+#define PPC_INST_SLBFEE                        0x7c0007a7
 
 #define PPC_INST_STRING                        0x7c00042a
 #define PPC_INST_STRING_MASK           0xfc0007fe
                                        __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
 #define PPC_ERATSX_DOT(t, a, w)        stringify_in_c(.long PPC_INST_ERATSX_DOT | \
                                        __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
-
+#define PPC_SLBFEE_DOT(t, b)   stringify_in_c(.long PPC_INST_SLBFEE | \
+                                       __PPC_RT(t) | __PPC_RB(b))
 
 /*
  * Define what the VSX XX1 form instructions will look like, then add
index b585bff1a022528c23a4193b2217ce4fde44b92d..8e2d0371fe1e71f0460dc1e28f7ba2d2a193aec0 100644 (file)
@@ -385,6 +385,36 @@ static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
 extern unsigned long cpuidle_disable;
 enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
 
+extern int powersave_nap;      /* set if nap mode can be used in idle loop */
+void cpu_idle_wait(void);
+
+#ifdef CONFIG_PSERIES_IDLE
+extern void update_smt_snooze_delay(int snooze);
+extern int pseries_notify_cpuidle_add_cpu(int cpu);
+#else
+static inline void update_smt_snooze_delay(int snooze) {}
+static inline int pseries_notify_cpuidle_add_cpu(int cpu) { return 0; }
+#endif
+
+extern void flush_instruction_cache(void);
+extern void hard_reset_now(void);
+extern void poweroff_now(void);
+extern int fix_alignment(struct pt_regs *);
+extern void cvt_fd(float *from, double *to);
+extern void cvt_df(double *from, float *to);
+extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+
+#ifdef CONFIG_PPC64
+/*
+ * We handle most unaligned accesses in hardware. On the other hand 
+ * unaligned DMA can be very expensive on some ppc64 IO chips (it does
+ * powers of 2 writes until it reaches sufficient alignment).
+ *
+ * Based on this we disable the IP header alignment in network drivers.
+ */
+#define NET_IP_ALIGN   0
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PROCESSOR_H */
index b1a215eabef6abc872ae94107a1be3af3c2bdad6..9d7f0fb690285bd0bb183e375080518e695792cb 100644 (file)
 #define   DSISR_ISSTORE                0x02000000      /* access was a store */
 #define   DSISR_DABRMATCH      0x00400000      /* hit data breakpoint */
 #define   DSISR_NOSEGMENT      0x00200000      /* STAB/SLB miss */
+#define   DSISR_KEYFAULT       0x00200000      /* Key fault */
 #define SPRN_TBRL      0x10C   /* Time Base Read Lower Register (user, R/O) */
 #define SPRN_TBRU      0x10D   /* Time Base Read Upper Register (user, R/O) */
 #define SPRN_TBWL      0x11C   /* Time Base Lower Register (super, R/W) */
 #define   LPCR_ISL     (1ul << (63-2))
 #define   LPCR_VC_SH   (63-2)
 #define   LPCR_DPFD_SH (63-11)
+#define   LPCR_VRMASD  (0x1ful << (63-16))
 #define   LPCR_VRMA_L  (1ul << (63-12))
 #define   LPCR_VRMA_LP0        (1ul << (63-15))
 #define   LPCR_VRMA_LP1        (1ul << (63-16))
 #define SPRN_SPRG7     0x117   /* Special Purpose Register General 7 */
 #define SPRN_SRR0      0x01A   /* Save/Restore Register 0 */
 #define SPRN_SRR1      0x01B   /* Save/Restore Register 1 */
+#define   SRR1_ISI_NOPT                0x40000000 /* ISI: Not found in hash */
+#define   SRR1_ISI_N_OR_G      0x10000000 /* ISI: Access is no-exec or G */
+#define   SRR1_ISI_PROT                0x08000000 /* ISI: Other protection fault */
 #define   SRR1_WAKEMASK                0x00380000 /* reason for wakeup */
 #define   SRR1_WAKESYSERR      0x00300000 /* System error */
 #define   SRR1_WAKEEE          0x00200000 /* External interrupt */
index 8a97aa7289d36b155a1e01df4211a261a7a110e8..b86faa9107da24338d661d7acf7ba455da413974 100644 (file)
 #ifndef __ASM_POWERPC_REG_BOOKE_H__
 #define __ASM_POWERPC_REG_BOOKE_H__
 
+#ifdef CONFIG_BOOKE_WDT
+extern u32 booke_wdt_enabled;
+extern u32 booke_wdt_period;
+#endif /* CONFIG_BOOKE_WDT */
+
 /* Machine State Register (MSR) Fields */
 #define MSR_GS         (1<<28) /* Guest state */
 #define MSR_UCLE       (1<<26) /* User-mode cache lock enable */
index 01c143bb77aed58b75bf68d2b47843b710e62efb..557cff845deed0b6281bf983ccb8684352ea9874 100644 (file)
@@ -74,7 +74,6 @@ struct rtas_suspend_me_data {
 /* RTAS event classes */
 #define RTAS_INTERNAL_ERROR            0x80000000 /* set bit 0 */
 #define RTAS_EPOW_WARNING              0x40000000 /* set bit 1 */
-#define RTAS_POWERMGM_EVENTS           0x20000000 /* set bit 2 */
 #define RTAS_HOTPLUG_EVENTS            0x10000000 /* set bit 3 */
 #define RTAS_IO_EVENTS                 0x08000000 /* set bit 4 */
 #define RTAS_EVENT_SCAN_ALL_EVENTS     0xffffffff
@@ -204,6 +203,39 @@ struct rtas_ext_event_log_v6 {
                                        /* Variable length.             */
 };
 
+/* pSeries event log format */
+
+/* Two bytes ASCII section IDs */
+#define PSERIES_ELOG_SECT_ID_PRIV_HDR          (('P' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_USER_HDR          (('U' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_PRIMARY_SRC       (('P' << 8) | 'S')
+#define PSERIES_ELOG_SECT_ID_EXTENDED_UH       (('E' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_FAILING_MTMS      (('M' << 8) | 'T')
+#define PSERIES_ELOG_SECT_ID_SECONDARY_SRC     (('S' << 8) | 'S')
+#define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR      (('D' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_FW_ERROR          (('S' << 8) | 'W')
+#define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID    (('L' << 8) | 'P')
+#define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R')
+#define PSERIES_ELOG_SECT_ID_HMC_ID            (('H' << 8) | 'M')
+#define PSERIES_ELOG_SECT_ID_EPOW              (('E' << 8) | 'P')
+#define PSERIES_ELOG_SECT_ID_IO_EVENT          (('I' << 8) | 'E')
+#define PSERIES_ELOG_SECT_ID_MANUFACT_INFO     (('M' << 8) | 'I')
+#define PSERIES_ELOG_SECT_ID_CALL_HOME         (('C' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_USER_DEF          (('U' << 8) | 'D')
+
+/* Vendor specific Platform Event Log Format, Version 6, section header */
+struct pseries_errorlog {
+       uint16_t id;                    /* 0x00 2-byte ASCII section ID */
+       uint16_t length;                /* 0x02 Section length in bytes */
+       uint8_t version;                /* 0x04 Section version         */
+       uint8_t subtype;                /* 0x05 Section subtype         */
+       uint16_t creator_component;     /* 0x06 Creator component ID    */
+       uint8_t data[];                 /* 0x08 Start of section data   */
+};
+
+struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
+                                             uint16_t section_id);
+
 /*
  * This can be set by the rtas_flash module so that it can get called
  * as the absolutely last thing before the kernel terminates.
@@ -325,5 +357,7 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
 static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
 #endif
 
+extern int call_rtas(const char *, int, int, unsigned long *, ...);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_RTAS_H */
diff --git a/arch/powerpc/include/asm/runlatch.h b/arch/powerpc/include/asm/runlatch.h
new file mode 100644 (file)
index 0000000..54e9b96
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_RUNLATCH_H
+#define _ASM_POWERPC_RUNLATCH_H
+
+#ifdef CONFIG_PPC64
+
+extern void __ppc64_runlatch_on(void);
+extern void __ppc64_runlatch_off(void);
+
+/*
+ * We manually hard enable-disable, this is called
+ * in the idle loop and we don't want to mess up
+ * with soft-disable/enable & interrupt replay.
+ */
+#define ppc64_runlatch_off()                                   \
+       do {                                                    \
+               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
+                   test_thread_local_flags(_TLF_RUNLATCH)) {   \
+                       unsigned long msr = mfmsr();            \
+                       __hard_irq_disable();                   \
+                       __ppc64_runlatch_off();                 \
+                       if (msr & MSR_EE)                       \
+                               __hard_irq_enable();            \
+               }                                               \
+       } while (0)
+
+#define ppc64_runlatch_on()                                    \
+       do {                                                    \
+               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
+                   !test_thread_local_flags(_TLF_RUNLATCH)) {  \
+                       unsigned long msr = mfmsr();            \
+                       __hard_irq_disable();                   \
+                       __ppc64_runlatch_on();                  \
+                       if (msr & MSR_EE)                       \
+                               __hard_irq_enable();            \
+               }                                               \
+       } while (0)
+#else
+#define ppc64_runlatch_on()
+#define ppc64_runlatch_off()
+#endif /* CONFIG_PPC64 */
+
+#endif /* _ASM_POWERPC_RUNLATCH_H */
index 186e0fb835bd247d836eeacdc591a1450dd93ac5..d084ce195fc3af11b6c37443ae3ecc37c59fa3d4 100644 (file)
@@ -5,6 +5,28 @@
 
 #ifndef __ASSEMBLY__
 extern void ppc_printk_progress(char *s, unsigned short hex);
-#endif
+
+extern unsigned int rtas_data;
+extern int mem_init_done;      /* set on boot once kmalloc can be called */
+extern int init_bootmem_done;  /* set once bootmem is available */
+extern phys_addr_t memory_limit;
+extern unsigned long klimit;
+extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
+
+extern void via_cuda_init(void);
+extern void read_rtc_time(void);
+extern void pmac_find_display(void);
+
+struct device_node;
+extern void note_scsi_host(struct device_node *, void *);
+
+/* Used in very early kernel initialization. */
+extern unsigned long reloc_offset(void);
+extern unsigned long add_reloc_offset(unsigned long);
+extern void reloc_got2(unsigned long);
+
+#define PTRRELOC(x)    ((typeof(x)) add_reloc_offset((unsigned long)(x)))
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_SETUP_H */
index adba970ce918595047e40ba2925849076acbffa9..ebc24dc5b1a13433aaeb1f5f21a8e48192d1d3cc 100644 (file)
@@ -122,7 +122,6 @@ extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
 extern void smp_muxed_ipi_message_pass(int cpu, int msg);
 extern irqreturn_t smp_ipi_demux(void);
 
-void smp_init_iSeries(void);
 void smp_init_pSeries(void);
 void smp_init_cell(void);
 void smp_init_celleb(void);
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..caf82d0
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_SWITCH_TO_H
+#define _ASM_POWERPC_SWITCH_TO_H
+
+struct thread_struct;
+struct task_struct;
+struct pt_regs;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+       struct task_struct *);
+#define switch_to(prev, next, last)    ((last) = __switch_to((prev), (next)))
+
+struct thread_struct;
+extern struct task_struct *_switch(struct thread_struct *prev,
+                                  struct thread_struct *next);
+
+extern void giveup_fpu(struct task_struct *);
+extern void disable_kernel_fp(void);
+extern void enable_kernel_fp(void);
+extern void flush_fp_to_thread(struct task_struct *);
+extern void enable_kernel_altivec(void);
+extern void giveup_altivec(struct task_struct *);
+extern void load_up_altivec(struct task_struct *);
+extern int emulate_altivec(struct pt_regs *);
+extern void __giveup_vsx(struct task_struct *);
+extern void giveup_vsx(struct task_struct *);
+extern void enable_kernel_spe(void);
+extern void giveup_spe(struct task_struct *);
+extern void load_up_spe(struct task_struct *);
+
+#ifndef CONFIG_SMP
+extern void discard_lazy_cpu_state(void);
+#else
+static inline void discard_lazy_cpu_state(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ALTIVEC
+extern void flush_altivec_to_thread(struct task_struct *);
+#else
+static inline void flush_altivec_to_thread(struct task_struct *t)
+{
+}
+#endif
+
+#ifdef CONFIG_VSX
+extern void flush_vsx_to_thread(struct task_struct *);
+#else
+static inline void flush_vsx_to_thread(struct task_struct *t)
+{
+}
+#endif
+
+#ifdef CONFIG_SPE
+extern void flush_spe_to_thread(struct task_struct *);
+#else
+static inline void flush_spe_to_thread(struct task_struct *t)
+{
+}
+#endif
+
+#endif /* _ASM_POWERPC_SWITCH_TO_H */
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
deleted file mode 100644 (file)
index a02883d..0000000
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- */
-#ifndef _ASM_POWERPC_SYSTEM_H
-#define _ASM_POWERPC_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-#include <asm/hw_irq.h>
-
-/*
- * Memory barrier.
- * The sync instruction guarantees that all memory accesses initiated
- * by this processor have been performed (with respect to all other
- * mechanisms that access memory).  The eieio instruction is a barrier
- * providing an ordering (separately) for (a) cacheable stores and (b)
- * loads and stores to non-cacheable memory (e.g. I/O devices).
- *
- * mb() prevents loads and stores being reordered across this point.
- * rmb() prevents loads being reordered across this point.
- * wmb() prevents stores being reordered across this point.
- * read_barrier_depends() prevents data-dependent loads being reordered
- *     across this point (nop on PPC).
- *
- * *mb() variants without smp_ prefix must order all types of memory
- * operations with one another. sync is the only instruction sufficient
- * to do this.
- *
- * For the smp_ barriers, ordering is for cacheable memory operations
- * only. We have to use the sync instruction for smp_mb(), since lwsync
- * doesn't order loads with respect to previous stores.  Lwsync can be
- * used for smp_rmb() and smp_wmb().
- *
- * However, on CPUs that don't support lwsync, lwsync actually maps to a
- * heavy-weight sync, so smp_wmb() can be a lighter-weight eieio.
- */
-#define mb()   __asm__ __volatile__ ("sync" : : : "memory")
-#define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
-#define wmb()  __asm__ __volatile__ ("sync" : : : "memory")
-#define read_barrier_depends()  do { } while(0)
-
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-
-#ifdef __KERNEL__
-#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
-#ifdef CONFIG_SMP
-
-#ifdef __SUBARCH_HAS_LWSYNC
-#    define SMPWMB      LWSYNC
-#else
-#    define SMPWMB      eieio
-#endif
-
-#define smp_mb()       mb()
-#define smp_rmb()      __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
-#define smp_wmb()      __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif /* CONFIG_SMP */
-
-/*
- * This is a barrier which prevents following instructions from being
- * started until the value of the argument x is known.  For example, if
- * x is a variable loaded from memory, this prevents following
- * instructions from being executed until the load has been performed.
- */
-#define data_barrier(x)        \
-       asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
-
-struct task_struct;
-struct pt_regs;
-
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
-
-extern int (*__debugger)(struct pt_regs *regs);
-extern int (*__debugger_ipi)(struct pt_regs *regs);
-extern int (*__debugger_bpt)(struct pt_regs *regs);
-extern int (*__debugger_sstep)(struct pt_regs *regs);
-extern int (*__debugger_iabr_match)(struct pt_regs *regs);
-extern int (*__debugger_dabr_match)(struct pt_regs *regs);
-extern int (*__debugger_fault_handler)(struct pt_regs *regs);
-
-#define DEBUGGER_BOILERPLATE(__NAME) \
-static inline int __NAME(struct pt_regs *regs) \
-{ \
-       if (unlikely(__ ## __NAME)) \
-               return __ ## __NAME(regs); \
-       return 0; \
-}
-
-DEBUGGER_BOILERPLATE(debugger)
-DEBUGGER_BOILERPLATE(debugger_ipi)
-DEBUGGER_BOILERPLATE(debugger_bpt)
-DEBUGGER_BOILERPLATE(debugger_sstep)
-DEBUGGER_BOILERPLATE(debugger_iabr_match)
-DEBUGGER_BOILERPLATE(debugger_dabr_match)
-DEBUGGER_BOILERPLATE(debugger_fault_handler)
-
-#else
-static inline int debugger(struct pt_regs *regs) { return 0; }
-static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
-static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
-static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
-static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
-static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
-static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
-#endif
-
-extern int set_dabr(unsigned long dabr);
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-extern void do_send_trap(struct pt_regs *regs, unsigned long address,
-                        unsigned long error_code, int signal_code, int brkpt);
-#else
-extern void do_dabr(struct pt_regs *regs, unsigned long address,
-                   unsigned long error_code);
-#endif
-extern void print_backtrace(unsigned long *);
-extern void flush_instruction_cache(void);
-extern void hard_reset_now(void);
-extern void poweroff_now(void);
-
-#ifdef CONFIG_6xx
-extern long _get_L2CR(void);
-extern long _get_L3CR(void);
-extern void _set_L2CR(unsigned long);
-extern void _set_L3CR(unsigned long);
-#else
-#define _get_L2CR()    0L
-#define _get_L3CR()    0L
-#define _set_L2CR(val) do { } while(0)
-#define _set_L3CR(val) do { } while(0)
-#endif
-
-extern void via_cuda_init(void);
-extern void read_rtc_time(void);
-extern void pmac_find_display(void);
-extern void giveup_fpu(struct task_struct *);
-extern void disable_kernel_fp(void);
-extern void enable_kernel_fp(void);
-extern void flush_fp_to_thread(struct task_struct *);
-extern void enable_kernel_altivec(void);
-extern void giveup_altivec(struct task_struct *);
-extern void load_up_altivec(struct task_struct *);
-extern int emulate_altivec(struct pt_regs *);
-extern void __giveup_vsx(struct task_struct *);
-extern void giveup_vsx(struct task_struct *);
-extern void enable_kernel_spe(void);
-extern void giveup_spe(struct task_struct *);
-extern void load_up_spe(struct task_struct *);
-extern int fix_alignment(struct pt_regs *);
-extern void cvt_fd(float *from, double *to);
-extern void cvt_df(double *from, float *to);
-
-#ifndef CONFIG_SMP
-extern void discard_lazy_cpu_state(void);
-#else
-static inline void discard_lazy_cpu_state(void)
-{
-}
-#endif
-
-#ifdef CONFIG_ALTIVEC
-extern void flush_altivec_to_thread(struct task_struct *);
-#else
-static inline void flush_altivec_to_thread(struct task_struct *t)
-{
-}
-#endif
-
-#ifdef CONFIG_VSX
-extern void flush_vsx_to_thread(struct task_struct *);
-#else
-static inline void flush_vsx_to_thread(struct task_struct *t)
-{
-}
-#endif
-
-#ifdef CONFIG_SPE
-extern void flush_spe_to_thread(struct task_struct *);
-#else
-static inline void flush_spe_to_thread(struct task_struct *t)
-{
-}
-#endif
-
-extern int call_rtas(const char *, int, int, unsigned long *, ...);
-extern void cacheable_memzero(void *p, unsigned int nb);
-extern void *cacheable_memcpy(void *, const void *, unsigned int);
-extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
-extern void bad_page_fault(struct pt_regs *, unsigned long, int);
-extern void _exception(int, struct pt_regs *, int, unsigned long);
-extern void die(const char *, struct pt_regs *, long);
-extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
-
-#ifdef CONFIG_BOOKE_WDT
-extern u32 booke_wdt_enabled;
-extern u32 booke_wdt_period;
-#endif /* CONFIG_BOOKE_WDT */
-
-struct device_node;
-extern void note_scsi_host(struct device_node *, void *);
-
-extern struct task_struct *__switch_to(struct task_struct *,
-       struct task_struct *);
-#define switch_to(prev, next, last)    ((last) = __switch_to((prev), (next)))
-
-struct thread_struct;
-extern struct task_struct *_switch(struct thread_struct *prev,
-                                  struct thread_struct *next);
-
-extern unsigned int rtas_data;
-extern int mem_init_done;      /* set on boot once kmalloc can be called */
-extern int init_bootmem_done;  /* set once bootmem is available */
-extern phys_addr_t memory_limit;
-extern unsigned long klimit;
-extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
-
-extern int powersave_nap;      /* set if nap mode can be used in idle loop */
-void cpu_idle_wait(void);
-
-#ifdef CONFIG_PSERIES_IDLE
-extern void update_smt_snooze_delay(int snooze);
-extern int pseries_notify_cpuidle_add_cpu(int cpu);
-#else
-static inline void update_smt_snooze_delay(int snooze) {}
-static inline int pseries_notify_cpuidle_add_cpu(int cpu) { return 0; }
-#endif
-
-/*
- * Atomic exchange
- *
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
-static __always_inline unsigned long
-__xchg_u32(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
-"1:    lwarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %3,0,%2 \n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-
-/*
- * Atomic exchange
- *
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
-static __always_inline unsigned long
-__xchg_u32_local(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-"1:    lwarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %3,0,%2 \n\
-       bne-    1b"
-       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-
-#ifdef CONFIG_PPC64
-static __always_inline unsigned long
-__xchg_u64(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
-"1:    ldarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stdcx.  %3,0,%2 \n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-
-static __always_inline unsigned long
-__xchg_u64_local(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-"1:    ldarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stdcx.  %3,0,%2 \n\
-       bne-    1b"
-       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-#endif
-
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid xchg().
- */
-extern void __xchg_called_with_bad_pointer(void);
-
-static __always_inline unsigned long
-__xchg(volatile void *ptr, unsigned long x, unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __xchg_u32(ptr, x);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __xchg_u64(ptr, x);
-#endif
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-static __always_inline unsigned long
-__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __xchg_u32_local(ptr, x);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __xchg_u64_local(ptr, x);
-#endif
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-#define xchg(ptr,x)                                                         \
-  ({                                                                        \
-     __typeof__(*(ptr)) _x_ = (x);                                          \
-     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
-  })
-
-#define xchg_local(ptr,x)                                                   \
-  ({                                                                        \
-     __typeof__(*(ptr)) _x_ = (x);                                          \
-     (__typeof__(*(ptr))) __xchg_local((ptr),                               \
-               (unsigned long)_x_, sizeof(*(ptr)));                         \
-  })
-
-/*
- * Compare and exchange - if *p == old, set it to new,
- * and return the old value of *p.
- */
-#define __HAVE_ARCH_CMPXCHG    1
-
-static __always_inline unsigned long
-__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
-{
-       unsigned int prev;
-
-       __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
-"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
-       cmpw    0,%0,%3\n\
-       bne-    2f\n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %4,0,%2\n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-
-static __always_inline unsigned long
-__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
-                       unsigned long new)
-{
-       unsigned int prev;
-
-       __asm__ __volatile__ (
-"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
-       cmpw    0,%0,%3\n\
-       bne-    2f\n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %4,0,%2\n\
-       bne-    1b"
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-
-#ifdef CONFIG_PPC64
-static __always_inline unsigned long
-__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
-"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
-       cmpd    0,%0,%3\n\
-       bne-    2f\n\
-       stdcx.  %4,0,%2\n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-
-static __always_inline unsigned long
-__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
-                       unsigned long new)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__ (
-"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
-       cmpd    0,%0,%3\n\
-       bne-    2f\n\
-       stdcx.  %4,0,%2\n\
-       bne-    1b"
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-#endif
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static __always_inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
-         unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-#endif
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-static __always_inline unsigned long
-__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
-         unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32_local(ptr, old, new);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __cmpxchg_u64_local(ptr, old, new);
-#endif
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                              \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-
-#define cmpxchg_local(ptr, o, n)                                        \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,    \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-#ifdef CONFIG_PPC64
-/*
- * We handle most unaligned accesses in hardware. On the other hand 
- * unaligned DMA can be very expensive on some ppc64 IO chips (it does
- * powers of 2 writes until it reaches sufficient alignment).
- *
- * Based on this we disable the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN   0
-
-#define cmpxchg64(ptr, o, n)                                           \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg((ptr), (o), (n));                                       \
-  })
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-#else
-#include <asm-generic/cmpxchg-local.h>
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-/* Used in very early kernel initialization. */
-extern unsigned long reloc_offset(void);
-extern unsigned long add_reloc_offset(unsigned long);
-extern void reloc_got2(unsigned long);
-
-#define PTRRELOC(x)    ((typeof(x)) add_reloc_offset((unsigned long)(x)))
-
-extern struct dentry *powerpc_debugfs_root;
-
-#ifdef CONFIG_PPC64
-
-extern void __ppc64_runlatch_on(void);
-extern void __ppc64_runlatch_off(void);
-
-/*
- * We manually hard enable-disable, this is called
- * in the idle loop and we don't want to mess up
- * with soft-disable/enable & interrupt replay.
- */
-#define ppc64_runlatch_off()                                   \
-       do {                                                    \
-               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
-                   test_thread_local_flags(_TLF_RUNLATCH)) {   \
-                       unsigned long msr = mfmsr();            \
-                       __hard_irq_disable();                   \
-                       __ppc64_runlatch_off();                 \
-                       if (msr & MSR_EE)                       \
-                               __hard_irq_enable();            \
-               }                                               \
-       } while (0)
-
-#define ppc64_runlatch_on()                                    \
-       do {                                                    \
-               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
-                   !test_thread_local_flags(_TLF_RUNLATCH)) {  \
-                       unsigned long msr = mfmsr();            \
-                       __hard_irq_disable();                   \
-                       __ppc64_runlatch_on();                  \
-                       if (msr & MSR_EE)                       \
-                               __hard_irq_enable();            \
-               }                                               \
-       } while (0)
-#else
-#define ppc64_runlatch_on()
-#define ppc64_runlatch_off()
-#endif /* CONFIG_PPC64 */
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_SYSTEM_H */
index 8338aef5a4d3ee7fe556b188e56057cb3ea076bf..b3038817b8dc2a863287a5d0370d22e615e1377d 100644 (file)
@@ -44,7 +44,6 @@ extern void __init udbg_init_debug_lpar_hvsi(void);
 extern void __init udbg_init_pmac_realmode(void);
 extern void __init udbg_init_maple_realmode(void);
 extern void __init udbg_init_pas_realmode(void);
-extern void __init udbg_init_iseries(void);
 extern void __init udbg_init_rtas_panel(void);
 extern void __init udbg_init_rtas_console(void);
 extern void __init udbg_init_debug_beat(void);
index 0a290a19594645b41ac386a21576459705756b7a..6bfd5ffe1d4fd287141523e10d1589d89472b636 100644 (file)
@@ -69,6 +69,7 @@ struct vio_dev {
 };
 
 struct vio_driver {
+       const char *name;
        const struct vio_device_id *id_table;
        int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
        int (*remove)(struct vio_dev *dev);
@@ -76,10 +77,17 @@ struct vio_driver {
         * be loaded in a CMO environment if it uses DMA.
         */
        unsigned long (*get_desired_dma)(struct vio_dev *dev);
+       const struct dev_pm_ops *pm;
        struct device_driver driver;
 };
 
-extern int vio_register_driver(struct vio_driver *drv);
+extern int __vio_register_driver(struct vio_driver *drv, struct module *owner,
+                                const char *mod_name);
+/*
+ * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
+ */
+#define vio_register_driver(driver)            \
+       __vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
 extern void vio_unregister_driver(struct vio_driver *drv);
 
 extern int vio_cmo_entitlement_update(size_t);
index 8184ee97e484e9b86dcb8c0d0f226e88066796d4..ee5b690a0bedff7f4e9e6f485e9dc3c31df31a8a 100644 (file)
 #include <linux/mm.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/cputable.h>
 #include <asm/emulated_ops.h>
+#include <asm/switch_to.h>
 
 struct aligninfo {
        unsigned char len;
index cc492e48ddfac1bf1db71b16b739799a7f929111..34b8afe94a500f1b7191bce06ad23b2b32427725 100644 (file)
@@ -412,16 +412,23 @@ int main(void)
        DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2));
        DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3));
 #endif
-       DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
-       DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
-       DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
-       DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
+       DEFINE(VCPU_SHARED_SPRG4, offsetof(struct kvm_vcpu_arch_shared, sprg4));
+       DEFINE(VCPU_SHARED_SPRG5, offsetof(struct kvm_vcpu_arch_shared, sprg5));
+       DEFINE(VCPU_SHARED_SPRG6, offsetof(struct kvm_vcpu_arch_shared, sprg6));
+       DEFINE(VCPU_SHARED_SPRG7, offsetof(struct kvm_vcpu_arch_shared, sprg7));
        DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
        DEFINE(VCPU_SHADOW_PID1, offsetof(struct kvm_vcpu, arch.shadow_pid1));
        DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
        DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
        DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
 
+       DEFINE(VCPU_SHARED_MAS0, offsetof(struct kvm_vcpu_arch_shared, mas0));
+       DEFINE(VCPU_SHARED_MAS1, offsetof(struct kvm_vcpu_arch_shared, mas1));
+       DEFINE(VCPU_SHARED_MAS2, offsetof(struct kvm_vcpu_arch_shared, mas2));
+       DEFINE(VCPU_SHARED_MAS7_3, offsetof(struct kvm_vcpu_arch_shared, mas7_3));
+       DEFINE(VCPU_SHARED_MAS4, offsetof(struct kvm_vcpu_arch_shared, mas4));
+       DEFINE(VCPU_SHARED_MAS6, offsetof(struct kvm_vcpu_arch_shared, mas6));
+
        /* book3s */
 #ifdef CONFIG_KVM_BOOK3S_64_HV
        DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
@@ -434,6 +441,7 @@ int main(void)
        DEFINE(KVM_LAST_VCPU, offsetof(struct kvm, arch.last_vcpu));
        DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
        DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
+       DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
        DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
        DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
 #endif
index 138ae183c44005bad8e2694aa7b21c85208e2284..455faa389876e51f3afaa732f74949b6859ae95c 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/cputable.h>
 #include <asm/prom.h>          /* for PTRRELOC on ARCH=ppc */
 #include <asm/mmu.h>
+#include <asm/setup.h>
 
 struct cpu_spec* cur_cpu_spec = NULL;
 EXPORT_SYMBOL(cur_cpu_spec);
index abef75176c079f2f72f71d6af4f10cec4095deca..fdcd8f551affe3225f8f7da271a4b630c99bd5f5 100644 (file)
@@ -27,8 +27,8 @@
 #include <asm/kdump.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/setjmp.h>
+#include <asm/debug.h>
 
 /*
  * The primary CPU waits a while for all secondary CPUs to enter. This is to
index 2d0868a4e2f0d3d4b346721c1a25fad8ef717316..cb705fdbb4583b6b162c9c2cb8991be43525eea4 100644 (file)
@@ -101,14 +101,14 @@ data_access_not_stab:
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
 #endif
        EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
-                                KVMTEST_PR, 0x300)
+                                KVMTEST, 0x300)
 
        . = 0x380
        .globl data_access_slb_pSeries
 data_access_slb_pSeries:
        HMT_MEDIUM
        SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
+       EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380)
        std     r3,PACA_EXSLB+EX_R3(r13)
        mfspr   r3,SPRN_DAR
 #ifdef __DISABLED__
@@ -330,8 +330,8 @@ do_stab_bolted_pSeries:
        EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
 #endif /* CONFIG_POWER4_ONLY */
 
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x300)
-       KVM_HANDLER_PR_SKIP(PACA_EXSLB, EXC_STD, 0x380)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
+       KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400)
        KVM_HANDLER_PR(PACA_EXSLB, EXC_STD, 0x480)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
index e8e821146f3813292390e803ca07fba062e2a1cb..6d2209ac0c44def75981aaf6509427acc5ebee1e 100644 (file)
 #include <linux/sysctl.h>
 #include <linux/tick.h>
 
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
+#include <asm/runlatch.h>
 #include <asm/smp.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
index a3d128e94cff4b9753810ebd6e09d9410cd9760a..243dbabfe74dff0ebbe55fab216a335574c1dc12 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/of_irq.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
@@ -67,6 +66,7 @@
 #include <asm/machdep.h>
 #include <asm/udbg.h>
 #include <asm/smp.h>
+#include <asm/debug.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
@@ -208,8 +208,8 @@ notrace void arch_local_irq_restore(unsigned long en)
         * we are checking the "new" CPU instead of the old one. This
         * is only a problem if an event happened on the "old" CPU.
         *
-        * External interrupt events on non-iseries will have caused
-        * interrupts to be hard-disabled, so there is no problem, we
+        * External interrupt events will have caused interrupts to
+        * be hard-disabled, so there is no problem, we
         * cannot have preempted.
         */
        irq_happened = get_irq_happened();
@@ -445,9 +445,9 @@ void do_IRQ(struct pt_regs *regs)
        may_hard_irq_enable();
 
        /* And finally process it */
-       if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
+       if (irq != NO_IRQ)
                handle_one_irq(irq);
-       else if (irq != NO_IRQ_IGNORE)
+       else
                __get_cpu_var(irq_stat).spurious_irqs++;
 
        irq_exit();
index bc47352deb1fec8f76fc1ac9f094c941cc2a9e4f..e88c6433181958ca5f961186899098b561104fd2 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/cacheflush.h>
 #include <asm/sstep.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 #define MSR_SINGLESTEP (MSR_DE)
index 2985338d0e10164e3b77ab12fcc3bb755a1a6fb3..62bdf238966985d8b98d84105b3fd4d108601194 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
  * Authors:
  *     Alexander Graf <agraf@suse.de>
@@ -29,6 +30,7 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
+#include <asm/ppc-opcode.h>
 
 #define KVM_MAGIC_PAGE         (-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
 #define KVM_INST_B             0x48000000
 #define KVM_INST_B_MASK                0x03ffffff
 #define KVM_INST_B_MAX         0x01ffffff
+#define KVM_INST_LI            0x38000000
 
 #define KVM_MASK_RT            0x03e00000
 #define KVM_RT_30              0x03c00000
 #define KVM_MASK_RB            0x0000f800
 #define KVM_INST_MFMSR         0x7c0000a6
-#define KVM_INST_MFSPR_SPRG0   0x7c1042a6
-#define KVM_INST_MFSPR_SPRG1   0x7c1142a6
-#define KVM_INST_MFSPR_SPRG2   0x7c1242a6
-#define KVM_INST_MFSPR_SPRG3   0x7c1342a6
-#define KVM_INST_MFSPR_SRR0    0x7c1a02a6
-#define KVM_INST_MFSPR_SRR1    0x7c1b02a6
-#define KVM_INST_MFSPR_DAR     0x7c1302a6
-#define KVM_INST_MFSPR_DSISR   0x7c1202a6
-
-#define KVM_INST_MTSPR_SPRG0   0x7c1043a6
-#define KVM_INST_MTSPR_SPRG1   0x7c1143a6
-#define KVM_INST_MTSPR_SPRG2   0x7c1243a6
-#define KVM_INST_MTSPR_SPRG3   0x7c1343a6
-#define KVM_INST_MTSPR_SRR0    0x7c1a03a6
-#define KVM_INST_MTSPR_SRR1    0x7c1b03a6
-#define KVM_INST_MTSPR_DAR     0x7c1303a6
-#define KVM_INST_MTSPR_DSISR   0x7c1203a6
+
+#define SPR_FROM               0
+#define SPR_TO                 0x100
+
+#define KVM_INST_SPR(sprn, moveto) (0x7c0002a6 | \
+                                   (((sprn) & 0x1f) << 16) | \
+                                   (((sprn) & 0x3e0) << 6) | \
+                                   (moveto))
+
+#define KVM_INST_MFSPR(sprn)   KVM_INST_SPR(sprn, SPR_FROM)
+#define KVM_INST_MTSPR(sprn)   KVM_INST_SPR(sprn, SPR_TO)
 
 #define KVM_INST_TLBSYNC       0x7c00046c
 #define KVM_INST_MTMSRD_L0     0x7c000164
 #define KVM_INST_MTMSRD_L1     0x7c010164
 #define KVM_INST_MTMSR         0x7c000124
 
+#define KVM_INST_WRTEE         0x7c000106
 #define KVM_INST_WRTEEI_0      0x7c000146
 #define KVM_INST_WRTEEI_1      0x7c008146
 
@@ -270,26 +268,27 @@ static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
 
 #ifdef CONFIG_BOOKE
 
-extern u32 kvm_emulate_wrteei_branch_offs;
-extern u32 kvm_emulate_wrteei_ee_offs;
-extern u32 kvm_emulate_wrteei_len;
-extern u32 kvm_emulate_wrteei[];
+extern u32 kvm_emulate_wrtee_branch_offs;
+extern u32 kvm_emulate_wrtee_reg_offs;
+extern u32 kvm_emulate_wrtee_orig_ins_offs;
+extern u32 kvm_emulate_wrtee_len;
+extern u32 kvm_emulate_wrtee[];
 
-static void kvm_patch_ins_wrteei(u32 *inst)
+static void kvm_patch_ins_wrtee(u32 *inst, u32 rt, int imm_one)
 {
        u32 *p;
        int distance_start;
        int distance_end;
        ulong next_inst;
 
-       p = kvm_alloc(kvm_emulate_wrteei_len * 4);
+       p = kvm_alloc(kvm_emulate_wrtee_len * 4);
        if (!p)
                return;
 
        /* Find out where we are and put everything there */
        distance_start = (ulong)p - (ulong)inst;
        next_inst = ((ulong)inst + 4);
-       distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_branch_offs];
+       distance_end = next_inst - (ulong)&p[kvm_emulate_wrtee_branch_offs];
 
        /* Make sure we only write valid b instructions */
        if (distance_start > KVM_INST_B_MAX) {
@@ -298,10 +297,65 @@ static void kvm_patch_ins_wrteei(u32 *inst)
        }
 
        /* Modify the chunk to fit the invocation */
-       memcpy(p, kvm_emulate_wrteei, kvm_emulate_wrteei_len * 4);
-       p[kvm_emulate_wrteei_branch_offs] |= distance_end & KVM_INST_B_MASK;
-       p[kvm_emulate_wrteei_ee_offs] |= (*inst & MSR_EE);
-       flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_len * 4);
+       memcpy(p, kvm_emulate_wrtee, kvm_emulate_wrtee_len * 4);
+       p[kvm_emulate_wrtee_branch_offs] |= distance_end & KVM_INST_B_MASK;
+
+       if (imm_one) {
+               p[kvm_emulate_wrtee_reg_offs] =
+                       KVM_INST_LI | __PPC_RT(30) | MSR_EE;
+       } else {
+               /* Make clobbered registers work too */
+               switch (get_rt(rt)) {
+               case 30:
+                       kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs],
+                                        magic_var(scratch2), KVM_RT_30);
+                       break;
+               case 31:
+                       kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs],
+                                        magic_var(scratch1), KVM_RT_30);
+                       break;
+               default:
+                       p[kvm_emulate_wrtee_reg_offs] |= rt;
+                       break;
+               }
+       }
+
+       p[kvm_emulate_wrtee_orig_ins_offs] = *inst;
+       flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrtee_len * 4);
+
+       /* Patch the invocation */
+       kvm_patch_ins_b(inst, distance_start);
+}
+
+extern u32 kvm_emulate_wrteei_0_branch_offs;
+extern u32 kvm_emulate_wrteei_0_len;
+extern u32 kvm_emulate_wrteei_0[];
+
+static void kvm_patch_ins_wrteei_0(u32 *inst)
+{
+       u32 *p;
+       int distance_start;
+       int distance_end;
+       ulong next_inst;
+
+       p = kvm_alloc(kvm_emulate_wrteei_0_len * 4);
+       if (!p)
+               return;
+
+       /* Find out where we are and put everything there */
+       distance_start = (ulong)p - (ulong)inst;
+       next_inst = ((ulong)inst + 4);
+       distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_0_branch_offs];
+
+       /* Make sure we only write valid b instructions */
+       if (distance_start > KVM_INST_B_MAX) {
+               kvm_patching_worked = false;
+               return;
+       }
+
+       memcpy(p, kvm_emulate_wrteei_0, kvm_emulate_wrteei_0_len * 4);
+       p[kvm_emulate_wrteei_0_branch_offs] |= distance_end & KVM_INST_B_MASK;
+       flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_0_len * 4);
 
        /* Patch the invocation */
        kvm_patch_ins_b(inst, distance_start);
@@ -380,56 +434,191 @@ static void kvm_check_ins(u32 *inst, u32 features)
        case KVM_INST_MFMSR:
                kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG0:
+       case KVM_INST_MFSPR(SPRN_SPRG0):
                kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG1:
+       case KVM_INST_MFSPR(SPRN_SPRG1):
                kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG2:
+       case KVM_INST_MFSPR(SPRN_SPRG2):
                kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG3:
+       case KVM_INST_MFSPR(SPRN_SPRG3):
                kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
                break;
-       case KVM_INST_MFSPR_SRR0:
+       case KVM_INST_MFSPR(SPRN_SRR0):
                kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
                break;
-       case KVM_INST_MFSPR_SRR1:
+       case KVM_INST_MFSPR(SPRN_SRR1):
                kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
                break;
-       case KVM_INST_MFSPR_DAR:
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_DEAR):
+#else
+       case KVM_INST_MFSPR(SPRN_DAR):
+#endif
                kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
                break;
-       case KVM_INST_MFSPR_DSISR:
+       case KVM_INST_MFSPR(SPRN_DSISR):
                kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
                break;
 
+#ifdef CONFIG_PPC_BOOK3E_MMU
+       case KVM_INST_MFSPR(SPRN_MAS0):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas0), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS1):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas1), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS2):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(mas2), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS3):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas7_3) + 4, inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS4):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas4), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS6):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas6), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS7):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas7_3), inst_rt);
+               break;
+#endif /* CONFIG_PPC_BOOK3E_MMU */
+
+       case KVM_INST_MFSPR(SPRN_SPRG4):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG4R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg4), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_SPRG5):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG5R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg5), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_SPRG6):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG6R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg6), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_SPRG7):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG7R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg7), inst_rt);
+               break;
+
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_ESR):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(esr), inst_rt);
+               break;
+#endif
+
+       case KVM_INST_MFSPR(SPRN_PIR):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(pir), inst_rt);
+               break;
+
+
        /* Stores */
-       case KVM_INST_MTSPR_SPRG0:
+       case KVM_INST_MTSPR(SPRN_SPRG0):
                kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
                break;
-       case KVM_INST_MTSPR_SPRG1:
+       case KVM_INST_MTSPR(SPRN_SPRG1):
                kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
                break;
-       case KVM_INST_MTSPR_SPRG2:
+       case KVM_INST_MTSPR(SPRN_SPRG2):
                kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
                break;
-       case KVM_INST_MTSPR_SPRG3:
+       case KVM_INST_MTSPR(SPRN_SPRG3):
                kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
                break;
-       case KVM_INST_MTSPR_SRR0:
+       case KVM_INST_MTSPR(SPRN_SRR0):
                kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
                break;
-       case KVM_INST_MTSPR_SRR1:
+       case KVM_INST_MTSPR(SPRN_SRR1):
                kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
                break;
-       case KVM_INST_MTSPR_DAR:
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MTSPR(SPRN_DEAR):
+#else
+       case KVM_INST_MTSPR(SPRN_DAR):
+#endif
                kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
                break;
-       case KVM_INST_MTSPR_DSISR:
+       case KVM_INST_MTSPR(SPRN_DSISR):
                kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
                break;
+#ifdef CONFIG_PPC_BOOK3E_MMU
+       case KVM_INST_MTSPR(SPRN_MAS0):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas0), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS1):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas1), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS2):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(mas2), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS3):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas7_3) + 4, inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS4):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas4), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS6):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas6), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS7):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas7_3), inst_rt);
+               break;
+#endif /* CONFIG_PPC_BOOK3E_MMU */
+
+       case KVM_INST_MTSPR(SPRN_SPRG4):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg4), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_SPRG5):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg5), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_SPRG6):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg6), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_SPRG7):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg7), inst_rt);
+               break;
+
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MTSPR(SPRN_ESR):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(esr), inst_rt);
+               break;
+#endif
 
        /* Nops */
        case KVM_INST_TLBSYNC:
@@ -444,6 +633,11 @@ static void kvm_check_ins(u32 *inst, u32 features)
        case KVM_INST_MTMSRD_L0:
                kvm_patch_ins_mtmsr(inst, inst_rt);
                break;
+#ifdef CONFIG_BOOKE
+       case KVM_INST_WRTEE:
+               kvm_patch_ins_wrtee(inst, inst_rt, 0);
+               break;
+#endif
        }
 
        switch (inst_no_rt & ~KVM_MASK_RB) {
@@ -461,13 +655,19 @@ static void kvm_check_ins(u32 *inst, u32 features)
        switch (_inst) {
 #ifdef CONFIG_BOOKE
        case KVM_INST_WRTEEI_0:
+               kvm_patch_ins_wrteei_0(inst);
+               break;
+
        case KVM_INST_WRTEEI_1:
-               kvm_patch_ins_wrteei(inst);
+               kvm_patch_ins_wrtee(inst, 0, 1);
                break;
 #endif
        }
 }
 
+extern u32 kvm_template_start[];
+extern u32 kvm_template_end[];
+
 static void kvm_use_magic_page(void)
 {
        u32 *p;
@@ -488,8 +688,23 @@ static void kvm_use_magic_page(void)
        start = (void*)_stext;
        end = (void*)_etext;
 
-       for (p = start; p < end; p++)
+       /*
+        * Being interrupted in the middle of patching would
+        * be bad for SPRG4-7, which KVM can't keep in sync
+        * with emulated accesses because reads don't trap.
+        */
+       local_irq_disable();
+
+       for (p = start; p < end; p++) {
+               /* Avoid patching the template code */
+               if (p >= kvm_template_start && p < kvm_template_end) {
+                       p = kvm_template_end - 1;
+                       continue;
+               }
                kvm_check_ins(p, features);
+       }
+
+       local_irq_enable();
 
        printk(KERN_INFO "KVM: Live patching for a fast VM %s\n",
                         kvm_patching_worked ? "worked" : "failed");
index f2b1b2523e61118761d11dc5debd5e9e6f383bd6..e291cf3cf954b9c718fb240eceeed0823b6b436a 100644 (file)
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright SUSE Linux Products GmbH 2010
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
  * Authors: Alexander Graf <agraf@suse.de>
  */
@@ -65,6 +66,9 @@ kvm_hypercall_start:
           shared->critical == r1 and r2 is always != r1 */             \
        STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
 
+.global kvm_template_start
+kvm_template_start:
+
 .global kvm_emulate_mtmsrd
 kvm_emulate_mtmsrd:
 
@@ -167,6 +171,9 @@ maybe_stay_in_guest:
 kvm_emulate_mtmsr_reg2:
        ori     r30, r0, 0
 
+       /* Put MSR into magic page because we don't call mtmsr */
+       STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
        /* Check if we have to fetch an interrupt */
        lwz     r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
        cmpwi   r31, 0
@@ -174,15 +181,10 @@ kvm_emulate_mtmsr_reg2:
 
        /* Check if we may trigger an interrupt */
        andi.   r31, r30, MSR_EE
-       beq     no_mtmsr
-
-       b       do_mtmsr
+       bne     do_mtmsr
 
 no_mtmsr:
 
-       /* Put MSR into magic page because we don't call mtmsr */
-       STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
-
        SCRATCH_RESTORE
 
        /* Go back to caller */
@@ -210,24 +212,80 @@ kvm_emulate_mtmsr_orig_ins_offs:
 kvm_emulate_mtmsr_len:
        .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
 
+/* also used for wrteei 1 */
+.global kvm_emulate_wrtee
+kvm_emulate_wrtee:
+
+       SCRATCH_SAVE
+
+       /* Fetch old MSR in r31 */
+       LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+       /* Insert new MSR[EE] */
+kvm_emulate_wrtee_reg:
+       ori     r30, r0, 0
+       rlwimi  r31, r30, 0, MSR_EE
+
+       /*
+        * If MSR[EE] is now set, check for a pending interrupt.
+        * We could skip this if MSR[EE] was already on, but that
+        * should be rare, so don't bother.
+        */
+       andi.   r30, r30, MSR_EE
+
+       /* Put MSR into magic page because we don't call wrtee */
+       STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+       beq     no_wrtee
+
+       /* Check if we have to fetch an interrupt */
+       lwz     r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+       cmpwi   r30, 0
+       bne     do_wrtee
+
+no_wrtee:
+       SCRATCH_RESTORE
+
+       /* Go back to caller */
+kvm_emulate_wrtee_branch:
+       b       .
+
+do_wrtee:
+       SCRATCH_RESTORE
 
+       /* Just fire off the wrtee if it's critical */
+kvm_emulate_wrtee_orig_ins:
+       wrtee   r0
 
-.global kvm_emulate_wrteei
-kvm_emulate_wrteei:
+       b       kvm_emulate_wrtee_branch
 
+kvm_emulate_wrtee_end:
+
+.global kvm_emulate_wrtee_branch_offs
+kvm_emulate_wrtee_branch_offs:
+       .long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrtee_reg_offs
+kvm_emulate_wrtee_reg_offs:
+       .long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrtee_orig_ins_offs
+kvm_emulate_wrtee_orig_ins_offs:
+       .long (kvm_emulate_wrtee_orig_ins - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrtee_len
+kvm_emulate_wrtee_len:
+       .long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrteei_0
+kvm_emulate_wrteei_0:
        SCRATCH_SAVE
 
        /* Fetch old MSR in r31 */
        LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
 
        /* Remove MSR_EE from old MSR */
-       li      r30, 0
-       ori     r30, r30, MSR_EE
-       andc    r31, r31, r30
-
-       /* OR new MSR_EE onto the old MSR */
-kvm_emulate_wrteei_ee:
-       ori     r31, r31, 0
+       rlwinm  r31, r31, 0, ~MSR_EE
 
        /* Write new MSR value back */
        STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
@@ -235,22 +293,17 @@ kvm_emulate_wrteei_ee:
        SCRATCH_RESTORE
 
        /* Go back to caller */
-kvm_emulate_wrteei_branch:
+kvm_emulate_wrteei_0_branch:
        b       .
-kvm_emulate_wrteei_end:
-
-.global kvm_emulate_wrteei_branch_offs
-kvm_emulate_wrteei_branch_offs:
-       .long (kvm_emulate_wrteei_branch - kvm_emulate_wrteei) / 4
+kvm_emulate_wrteei_0_end:
 
-.global kvm_emulate_wrteei_ee_offs
-kvm_emulate_wrteei_ee_offs:
-       .long (kvm_emulate_wrteei_ee - kvm_emulate_wrteei) / 4
-
-.global kvm_emulate_wrteei_len
-kvm_emulate_wrteei_len:
-       .long (kvm_emulate_wrteei_end - kvm_emulate_wrteei) / 4
+.global kvm_emulate_wrteei_0_branch_offs
+kvm_emulate_wrteei_0_branch_offs:
+       .long (kvm_emulate_wrteei_0_branch - kvm_emulate_wrteei_0) / 4
 
+.global kvm_emulate_wrteei_0_len
+kvm_emulate_wrteei_0_len:
+       .long (kvm_emulate_wrteei_0_end - kvm_emulate_wrteei_0) / 4
 
 .global kvm_emulate_mtsrin
 kvm_emulate_mtsrin:
@@ -300,3 +353,6 @@ kvm_emulate_mtsrin_orig_ins_offs:
 .global kvm_emulate_mtsrin_len
 kvm_emulate_mtsrin_len:
        .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4
+
+.global kvm_template_end
+kvm_template_end:
index ac12bd80ad951e1be909e7c2dc92ac146bdb362b..f5725bce9ed29c55583b2805749a542628977698 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/hvcall.h>
 #include <asm/firmware.h>
 #include <asm/rtas.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/vdso_datapage.h>
index d3114a71dd32279e5ac92eeba75244821162f202..786a2700ec2d541d3544d23635b72b40dc75e64b 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/cuda.h>
 #include <linux/pmu.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pci-bridge.h>
 #include <asm/irq.h>
 #include <asm/pmac_feature.h>
@@ -43,6 +42,7 @@
 #include <asm/signal.h>
 #include <asm/dcr.h>
 #include <asm/ftrace.h>
+#include <asm/switch_to.h>
 
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
index e40707032ac36cd1c71b7796558a9716bbfe6bc8..f88698c0f332d2a0c87957d10f1ca32ddd3d5eb0 100644 (file)
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/time.h>
+#include <asm/runlatch.h>
 #include <asm/syscalls.h>
+#include <asm/switch_to.h>
+#include <asm/debug.h>
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #endif
index 89e850af3dd6c0277c550afbe57cbf69e11a92d9..f191bf02943a839dc243e0b9dcbbabe8f874eff1 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/paca.h>
 #include <asm/pgtable.h>
index e2d599048142e2d4d7084f803b2b5abd5fa70f43..99860273211b03a7c31958d0c8940bf56d51abec 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/pci.h>
@@ -447,7 +446,7 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason)
        if (RELOC(of_platform) == PLATFORM_POWERMAC)
                asm("trap\n");
 
-       /* ToDo: should put up an SRC here on p/iSeries */
+       /* ToDo: should put up an SRC here on pSeries */
        call_prom("exit", 0, 0);
 
        for (;;)                        /* should never get here */
index 5b43325402bcc8e5435c1e2804685e81cb24df72..8d8e028893be6e89346d89e984ae76b0a4cfb583 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
+#include <asm/switch_to.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
index 69c4be917d07e1331621994b572a6db30e2cb3cc..469349d14a97e18b56a3fae0d9b12362f325249c 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
+#include <asm/switch_to.h>
 
 /*
  * does not yet catch signals sent when the child dies.
index 9f843cdfee9ec69ac38ea7b78518f035b2266c4e..fcec38241f794f204e4f44a052c4b16ce25b125c 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/firmware.h>
 #include <asm/page.h>
 #include <asm/param.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/udbg.h>
@@ -868,6 +867,40 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 }
 #endif
 
+/**
+ * Find a specific pseries error log in an RTAS extended event log.
+ * @log: RTAS error/event log
+ * @section_id: two character section identifier
+ *
+ * Returns a pointer to the specified errorlog or NULL if not found.
+ */
+struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
+                                             uint16_t section_id)
+{
+       struct rtas_ext_event_log_v6 *ext_log =
+               (struct rtas_ext_event_log_v6 *)log->buffer;
+       struct pseries_errorlog *sect;
+       unsigned char *p, *log_end;
+
+       /* Check that we understand the format */
+       if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
+           ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
+           ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
+               return NULL;
+
+       log_end = log->buffer + log->extended_log_length;
+       p = ext_log->vendor_log;
+
+       while (p < log_end) {
+               sect = (struct pseries_errorlog *)p;
+               if (sect->id == section_id)
+                       return sect;
+               p += sect->length;
+       }
+
+       return NULL;
+}
+
 asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
 {
        struct rtas_args args;
index b0ebdeab9494386368fd4ce8b0f7ed39e9814977..afd4f051f3f249e6c6da4c63408a63295101e3bd 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/btext.h>
 #include <asm/nvram.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/iommu.h>
 #include <asm/serial.h>
index ac761081511355ee68854ee02ade12f17ef93e18..9825f29d1fafbcfd381aec51286137efa51830e9 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/btext.h>
 #include <asm/machdep.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pmac_feature.h>
 #include <asm/sections.h>
 #include <asm/nvram.h>
index 4cb8f1e9d0442a2a6631d93bc4ce03a05e69ba17..389bd4f0cdb10496f1d478fc44181612123f30d1 100644 (file)
@@ -52,7 +52,6 @@
 #include <asm/btext.h>
 #include <asm/nvram.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/iommu.h>
 #include <asm/serial.h>
@@ -598,7 +597,7 @@ void __init setup_arch(char **cmdline_p)
        /* Initialize the MMU context management stuff */
        mmu_context_init();
 
-       kvm_rma_init();
+       kvm_linear_init();
 
        ppc64_boot_msg(0x15, "Setup Done");
 }
index 7006b7f4267a7b7c3fa9337319c16f1556ceaac8..651c5963662b68ed098c04d1dbdc512f06f2fac1 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/debug.h>
 
 #include "signal.h"
 
index e061ef5dd4490dc0dfb20da69ab1551b69767e48..45eb998557f8c3fbd9f8de333f58b17a29c2c959 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/syscalls.h>
 #include <asm/sigcontext.h>
 #include <asm/vdso.h>
+#include <asm/switch_to.h>
 #ifdef CONFIG_PPC64
 #include "ppc32.h"
 #include <asm/unistd.h>
index a50b5ec281dcd70a9afcf62f8bd8966e977bb4ce..2692efdb154e210a5aa787e021ed960cb3bde591 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
 #include <asm/vdso.h>
+#include <asm/switch_to.h>
 
 #include "signal.h"
 
index 46695febc09f6e10b96c1b8edcb736f749f40db4..d9f94410fd7fa7147794d562892024bbc360c760 100644 (file)
 #include <asm/machdep.h>
 #include <asm/cputhreads.h>
 #include <asm/cputable.h>
-#include <asm/system.h>
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #endif
+#include <asm/debug.h>
 
 #ifdef DEBUG
 #include <asm/udbg.h>
index af0e8290b4fc4f90faf3f59136683c10f3c47971..29b2f81dd7092ba6c4c3882f5ecf112b4c6523c1 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 /* Eventually we may need a look-up table, but this works for now.
index 641f9adc620596e46d6b59b5f725643ce8124ad5..eae33e10b65fb4a1b8858872427ce16bbbf85634 100644 (file)
@@ -10,9 +10,9 @@
  */
 
 #include <linux/sched.h>
-#include <asm/system.h>
 #include <asm/current.h>
 #include <asm/mmu_context.h>
+#include <asm/switch_to.h>
 
 void save_processor_state(void)
 {
index 168e88480223790d95f4f2e46976e93c32d926a6..0e899e47c325b51ac8b3c89a79f1d1a8f9fd5ad3 100644 (file)
@@ -6,7 +6,6 @@
  * GPLv2
  */
 
-#include <asm/system.h>
 #include <asm/iommu.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
index 4e5bf1edc0f2e19690175719fcaf20bc2994237f..81c570633ead9b95424a06410ee08337b076f65a 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/mmu_context.h>
 #include <asm/ppc-pci.h>
 #include <asm/syscalls.h>
+#include <asm/switch_to.h>
 
 
 asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
index 0c683d376b1cddddf6a9da9a07644f18d7acbb92..3529446c2abd78a407f9b3a7fd9735ed49802656 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/machdep.h>
 #include <asm/smp.h>
 #include <asm/pmc.h>
-#include <asm/system.h>
 
 #include "cacheinfo.h"
 
index a750409ccc4e25b2743456bc3b492166b9f8c1c7..6aa0c663e247fe1417a1bef2eb2479204082ce09 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/emulated_ops.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
@@ -58,6 +57,8 @@
 #include <asm/ppc-opcode.h>
 #include <asm/rio.h>
 #include <asm/fadump.h>
+#include <asm/switch_to.h>
+#include <asm/debug.h>
 
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 int (*__debugger)(struct pt_regs *regs) __read_mostly;
index 57fa2c0a531c7c56765cc4a659bf28735cac0abf..c39c1ca77f46c6a83ada12367a31fb764596632b 100644 (file)
@@ -46,9 +46,6 @@ void __init udbg_early_init(void)
 #elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
        /* Maple real mode debug */
        udbg_init_maple_realmode();
-#elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
-       /* For iSeries - hit Ctrl-x Ctrl-x to see the output */
-       udbg_init_iseries();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
        udbg_init_debug_beat();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
index d36ee1055f88cf3b06e4c4ee2d683f8bd2f9c918..9eb5b9b536a71b704b62a6cc6b38660f80d426b4 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/memblock.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
@@ -721,10 +720,10 @@ static int __init vdso_init(void)
        vdso_data->version.minor = SYSTEMCFG_MINOR;
        vdso_data->processor = mfspr(SPRN_PVR);
        /*
-        * Fake the old platform number for pSeries and iSeries and add
+        * Fake the old platform number for pSeries and add
         * in LPAR bit if necessary
         */
-       vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
+       vdso_data->platform = 0x100;
        if (firmware_has_feature(FW_FEATURE_LPAR))
                vdso_data->platform |= 1;
        vdso_data->physicalMemorySize = memblock_phys_mem_size();
index bca3fc427b45fffae821440d8021ac9beb4de7bd..b2f7c8480bf6e853704ba20cb4787db7cb519a91 100644 (file)
@@ -1159,17 +1159,21 @@ static int vio_bus_remove(struct device *dev)
  * vio_register_driver: - Register a new vio driver
  * @drv:       The vio_driver structure to be registered.
  */
-int vio_register_driver(struct vio_driver *viodrv)
+int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
+                         const char *mod_name)
 {
-       printk(KERN_DEBUG "%s: driver %s registering\n", __func__,
-               viodrv->driver.name);
+       pr_debug("%s: driver %s registering\n", __func__, viodrv->name);
 
        /* fill in 'struct driver' fields */
+       viodrv->driver.name = viodrv->name;
+       viodrv->driver.pm = viodrv->pm;
        viodrv->driver.bus = &vio_bus_type;
+       viodrv->driver.owner = owner;
+       viodrv->driver.mod_name = mod_name;
 
        return driver_register(&viodrv->driver);
 }
-EXPORT_SYMBOL(vio_register_driver);
+EXPORT_SYMBOL(__vio_register_driver);
 
 /**
  * vio_unregister_driver - Remove registration of vio driver.
index 78133deb4b64d91e482c6c3b1579ce099f1ee1b5..8f64709ae3319d3a26ac4701b97b9b5a182f2081 100644 (file)
@@ -69,6 +69,7 @@ config KVM_BOOK3S_64
 config KVM_BOOK3S_64_HV
        bool "KVM support for POWER7 and PPC970 using hypervisor mode in host"
        depends on KVM_BOOK3S_64
+       select MMU_NOTIFIER
        ---help---
          Support running unmodified book3s_64 guest kernels in
          virtual machines on POWER7 and PPC970 processors that have
index e41ac6f7dcf15105aa4b784fce7d43d1599c4d64..7d54f4ed6d96e3b5fa41f57044f066567131a195 100644 (file)
@@ -258,7 +258,7 @@ static bool clear_irqprio(struct kvm_vcpu *vcpu, unsigned int priority)
        return true;
 }
 
-void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
+void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
 {
        unsigned long *pending = &vcpu->arch.pending_exceptions;
        unsigned long old_pending = vcpu->arch.pending_exceptions;
@@ -423,10 +423,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        regs->sprg1 = vcpu->arch.shared->sprg1;
        regs->sprg2 = vcpu->arch.shared->sprg2;
        regs->sprg3 = vcpu->arch.shared->sprg3;
-       regs->sprg4 = vcpu->arch.sprg4;
-       regs->sprg5 = vcpu->arch.sprg5;
-       regs->sprg6 = vcpu->arch.sprg6;
-       regs->sprg7 = vcpu->arch.sprg7;
+       regs->sprg4 = vcpu->arch.shared->sprg4;
+       regs->sprg5 = vcpu->arch.shared->sprg5;
+       regs->sprg6 = vcpu->arch.shared->sprg6;
+       regs->sprg7 = vcpu->arch.shared->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -450,10 +450,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        vcpu->arch.shared->sprg1 = regs->sprg1;
        vcpu->arch.shared->sprg2 = regs->sprg2;
        vcpu->arch.shared->sprg3 = regs->sprg3;
-       vcpu->arch.sprg4 = regs->sprg4;
-       vcpu->arch.sprg5 = regs->sprg5;
-       vcpu->arch.sprg6 = regs->sprg6;
-       vcpu->arch.sprg7 = regs->sprg7;
+       vcpu->arch.shared->sprg4 = regs->sprg4;
+       vcpu->arch.shared->sprg5 = regs->sprg5;
+       vcpu->arch.shared->sprg6 = regs->sprg6;
+       vcpu->arch.shared->sprg7 = regs->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -477,41 +477,10 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-/*
- * Get (and clear) the dirty memory log for a memory slot.
- */
-int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
-                                     struct kvm_dirty_log *log)
+void kvmppc_decrementer_func(unsigned long data)
 {
-       struct kvm_memory_slot *memslot;
-       struct kvm_vcpu *vcpu;
-       ulong ga, ga_end;
-       int is_dirty = 0;
-       int r;
-       unsigned long n;
-
-       mutex_lock(&kvm->slots_lock);
-
-       r = kvm_get_dirty_log(kvm, log, &is_dirty);
-       if (r)
-               goto out;
-
-       /* If nothing is dirty, don't bother messing with page tables. */
-       if (is_dirty) {
-               memslot = id_to_memslot(kvm->memslots, log->slot);
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
 
-               ga = memslot->base_gfn << PAGE_SHIFT;
-               ga_end = ga + (memslot->npages << PAGE_SHIFT);
-
-               kvm_for_each_vcpu(n, vcpu, kvm)
-                       kvmppc_mmu_pte_pflush(vcpu, ga, ga_end);
-
-               n = kvm_dirty_bitmap_bytes(memslot);
-               memset(memslot->dirty_bitmap, 0, n);
-       }
-
-       r = 0;
-out:
-       mutex_unlock(&kvm->slots_lock);
-       return r;
+       kvmppc_core_queue_dec(vcpu);
+       kvm_vcpu_kick(vcpu);
 }
index 9fecbfbce773205650a9d6d9cd77704a61757a38..f922c29bb234d9bc6f2baf44175e934b63de5f86 100644 (file)
@@ -151,13 +151,15 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        bool primary = false;
        bool evict = false;
        struct hpte_cache *pte;
+       int r = 0;
 
        /* Get host physical address for gpa */
        hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
        if (is_error_pfn(hpaddr)) {
                printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
                                 orig_pte->eaddr);
-               return -EINVAL;
+               r = -EINVAL;
+               goto out;
        }
        hpaddr <<= PAGE_SHIFT;
 
@@ -249,7 +251,8 @@ next_pteg:
 
        kvmppc_mmu_hpte_cache_map(vcpu, pte);
 
-       return 0;
+out:
+       return r;
 }
 
 static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
@@ -297,12 +300,14 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
        u64 gvsid;
        u32 sr;
        struct kvmppc_sid_map *map;
-       struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu);
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       int r = 0;
 
        if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) {
                /* Invalidate an entry */
                svcpu->sr[esid] = SR_INVALID;
-               return -ENOENT;
+               r = -ENOENT;
+               goto out;
        }
 
        map = find_sid_vsid(vcpu, gvsid);
@@ -315,17 +320,21 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
 
        dprintk_sr("MMU: mtsr %d, 0x%x\n", esid, sr);
 
-       return 0;
+out:
+       svcpu_put(svcpu);
+       return r;
 }
 
 void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu)
 {
        int i;
-       struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu);
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
 
        dprintk_sr("MMU: flushing all segments (%d)\n", ARRAY_SIZE(svcpu->sr));
        for (i = 0; i < ARRAY_SIZE(svcpu->sr); i++)
                svcpu->sr[i] = SR_INVALID;
+
+       svcpu_put(svcpu);
 }
 
 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
index fa2f08434ba5c5c867166262388c8dab0a86aca1..6f87f39a1ac21c03d9c965223e72dab525162fd5 100644 (file)
@@ -88,12 +88,14 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        int vflags = 0;
        int attempt = 0;
        struct kvmppc_sid_map *map;
+       int r = 0;
 
        /* Get host physical address for gpa */
        hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
        if (is_error_pfn(hpaddr)) {
                printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr);
-               return -EINVAL;
+               r = -EINVAL;
+               goto out;
        }
        hpaddr <<= PAGE_SHIFT;
        hpaddr |= orig_pte->raddr & (~0xfffULL & ~PAGE_MASK);
@@ -110,7 +112,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
                printk(KERN_ERR "KVM: Segment map for 0x%llx (0x%lx) failed\n",
                                vsid, orig_pte->eaddr);
                WARN_ON(true);
-               return -EINVAL;
+               r = -EINVAL;
+               goto out;
        }
 
        vsid = map->host_vsid;
@@ -131,8 +134,10 @@ map_again:
 
        /* In case we tried normal mapping already, let's nuke old entries */
        if (attempt > 1)
-               if (ppc_md.hpte_remove(hpteg) < 0)
-                       return -1;
+               if (ppc_md.hpte_remove(hpteg) < 0) {
+                       r = -1;
+                       goto out;
+               }
 
        ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M);
 
@@ -162,7 +167,8 @@ map_again:
                kvmppc_mmu_hpte_cache_map(vcpu, pte);
        }
 
-       return 0;
+out:
+       return r;
 }
 
 static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
@@ -207,25 +213,30 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
 
 static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid)
 {
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        int i;
        int max_slb_size = 64;
        int found_inval = -1;
        int r;
 
-       if (!to_svcpu(vcpu)->slb_max)
-               to_svcpu(vcpu)->slb_max = 1;
+       if (!svcpu->slb_max)
+               svcpu->slb_max = 1;
 
        /* Are we overwriting? */
-       for (i = 1; i < to_svcpu(vcpu)->slb_max; i++) {
-               if (!(to_svcpu(vcpu)->slb[i].esid & SLB_ESID_V))
+       for (i = 1; i < svcpu->slb_max; i++) {
+               if (!(svcpu->slb[i].esid & SLB_ESID_V))
                        found_inval = i;
-               else if ((to_svcpu(vcpu)->slb[i].esid & ESID_MASK) == esid)
-                       return i;
+               else if ((svcpu->slb[i].esid & ESID_MASK) == esid) {
+                       r = i;
+                       goto out;
+               }
        }
 
        /* Found a spare entry that was invalidated before */
-       if (found_inval > 0)
-               return found_inval;
+       if (found_inval > 0) {
+               r = found_inval;
+               goto out;
+       }
 
        /* No spare invalid entry, so create one */
 
@@ -233,30 +244,35 @@ static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid)
                max_slb_size = mmu_slb_size;
 
        /* Overflowing -> purge */
-       if ((to_svcpu(vcpu)->slb_max) == max_slb_size)
+       if ((svcpu->slb_max) == max_slb_size)
                kvmppc_mmu_flush_segments(vcpu);
 
-       r = to_svcpu(vcpu)->slb_max;
-       to_svcpu(vcpu)->slb_max++;
+       r = svcpu->slb_max;
+       svcpu->slb_max++;
 
+out:
+       svcpu_put(svcpu);
        return r;
 }
 
 int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
 {
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        u64 esid = eaddr >> SID_SHIFT;
        u64 slb_esid = (eaddr & ESID_MASK) | SLB_ESID_V;
        u64 slb_vsid = SLB_VSID_USER;
        u64 gvsid;
        int slb_index;
        struct kvmppc_sid_map *map;
+       int r = 0;
 
        slb_index = kvmppc_mmu_next_segment(vcpu, eaddr & ESID_MASK);
 
        if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) {
                /* Invalidate an entry */
-               to_svcpu(vcpu)->slb[slb_index].esid = 0;
-               return -ENOENT;
+               svcpu->slb[slb_index].esid = 0;
+               r = -ENOENT;
+               goto out;
        }
 
        map = find_sid_vsid(vcpu, gvsid);
@@ -269,18 +285,22 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
        slb_vsid &= ~SLB_VSID_KP;
        slb_esid |= slb_index;
 
-       to_svcpu(vcpu)->slb[slb_index].esid = slb_esid;
-       to_svcpu(vcpu)->slb[slb_index].vsid = slb_vsid;
+       svcpu->slb[slb_index].esid = slb_esid;
+       svcpu->slb[slb_index].vsid = slb_vsid;
 
        trace_kvm_book3s_slbmte(slb_vsid, slb_esid);
 
-       return 0;
+out:
+       svcpu_put(svcpu);
+       return r;
 }
 
 void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu)
 {
-       to_svcpu(vcpu)->slb_max = 1;
-       to_svcpu(vcpu)->slb[0].esid = 0;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->slb_max = 1;
+       svcpu->slb[0].esid = 0;
+       svcpu_put(svcpu);
 }
 
 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
index bc3a2ea94217ef87962c3707b0cb7bd03330c73c..ddc485a529f2d7f7c59e22729fd55372eac9be03 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/vmalloc.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/ppc-opcode.h>
 #include <asm/cputable.h>
 
-/* For now use fixed-size 16MB page table */
-#define HPT_ORDER      24
-#define HPT_NPTEG      (1ul << (HPT_ORDER - 7))        /* 128B per pteg */
-#define HPT_HASH_MASK  (HPT_NPTEG - 1)
-
-/* Pages in the VRMA are 16MB pages */
-#define VRMA_PAGE_ORDER        24
-#define VRMA_VSID      0x1ffffffUL     /* 1TB VSID reserved for VRMA */
-
 /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
 #define MAX_LPID_970   63
 #define NR_LPIDS       (LPID_RSVD + 1)
@@ -51,21 +43,41 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
 {
        unsigned long hpt;
        unsigned long lpid;
+       struct revmap_entry *rev;
+       struct kvmppc_linear_info *li;
+
+       /* Allocate guest's hashed page table */
+       li = kvm_alloc_hpt();
+       if (li) {
+               /* using preallocated memory */
+               hpt = (ulong)li->base_virt;
+               kvm->arch.hpt_li = li;
+       } else {
+               /* using dynamic memory */
+               hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
+                                      __GFP_NOWARN, HPT_ORDER - PAGE_SHIFT);
+       }
 
-       hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
-                              HPT_ORDER - PAGE_SHIFT);
        if (!hpt) {
                pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
                return -ENOMEM;
        }
        kvm->arch.hpt_virt = hpt;
 
+       /* Allocate reverse map array */
+       rev = vmalloc(sizeof(struct revmap_entry) * HPT_NPTE);
+       if (!rev) {
+               pr_err("kvmppc_alloc_hpt: Couldn't alloc reverse map array\n");
+               goto out_freehpt;
+       }
+       kvm->arch.revmap = rev;
+
+       /* Allocate the guest's logical partition ID */
        do {
                lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS);
                if (lpid >= NR_LPIDS) {
                        pr_err("kvm_alloc_hpt: No LPIDs free\n");
-                       free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
-                       return -ENOMEM;
+                       goto out_freeboth;
                }
        } while (test_and_set_bit(lpid, lpid_inuse));
 
@@ -74,37 +86,64 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
 
        pr_info("KVM guest htab at %lx, LPID %lx\n", hpt, lpid);
        return 0;
+
+ out_freeboth:
+       vfree(rev);
+ out_freehpt:
+       free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
+       return -ENOMEM;
 }
 
 void kvmppc_free_hpt(struct kvm *kvm)
 {
        clear_bit(kvm->arch.lpid, lpid_inuse);
-       free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+       vfree(kvm->arch.revmap);
+       if (kvm->arch.hpt_li)
+               kvm_release_hpt(kvm->arch.hpt_li);
+       else
+               free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+}
+
+/* Bits in first HPTE dword for pagesize 4k, 64k or 16M */
+static inline unsigned long hpte0_pgsize_encoding(unsigned long pgsize)
+{
+       return (pgsize > 0x1000) ? HPTE_V_LARGE : 0;
+}
+
+/* Bits in second HPTE dword for pagesize 4k, 64k or 16M */
+static inline unsigned long hpte1_pgsize_encoding(unsigned long pgsize)
+{
+       return (pgsize == 0x10000) ? 0x1000 : 0;
 }
 
-void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
+void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
+                    unsigned long porder)
 {
        unsigned long i;
-       unsigned long npages = kvm->arch.ram_npages;
-       unsigned long pfn;
-       unsigned long *hpte;
-       unsigned long hash;
-       struct kvmppc_pginfo *pginfo = kvm->arch.ram_pginfo;
+       unsigned long npages;
+       unsigned long hp_v, hp_r;
+       unsigned long addr, hash;
+       unsigned long psize;
+       unsigned long hp0, hp1;
+       long ret;
 
-       if (!pginfo)
-               return;
+       psize = 1ul << porder;
+       npages = memslot->npages >> (porder - PAGE_SHIFT);
 
        /* VRMA can't be > 1TB */
-       if (npages > 1ul << (40 - kvm->arch.ram_porder))
-               npages = 1ul << (40 - kvm->arch.ram_porder);
+       if (npages > 1ul << (40 - porder))
+               npages = 1ul << (40 - porder);
        /* Can't use more than 1 HPTE per HPTEG */
        if (npages > HPT_NPTEG)
                npages = HPT_NPTEG;
 
+       hp0 = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
+               HPTE_V_BOLTED | hpte0_pgsize_encoding(psize);
+       hp1 = hpte1_pgsize_encoding(psize) |
+               HPTE_R_R | HPTE_R_C | HPTE_R_M | PP_RWXX;
+
        for (i = 0; i < npages; ++i) {
-               pfn = pginfo[i].pfn;
-               if (!pfn)
-                       break;
+               addr = i << porder;
                /* can't use hpt_hash since va > 64 bits */
                hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
                /*
@@ -113,15 +152,15 @@ void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
                 * at most one HPTE per HPTEG, we just assume entry 7
                 * is available and use it.
                 */
-               hpte = (unsigned long *) (kvm->arch.hpt_virt + (hash << 7));
-               hpte += 7 * 2;
-               /* HPTE low word - RPN, protection, etc. */
-               hpte[1] = (pfn << PAGE_SHIFT) | HPTE_R_R | HPTE_R_C |
-                       HPTE_R_M | PP_RWXX;
-               wmb();
-               hpte[0] = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
-                       (i << (VRMA_PAGE_ORDER - 16)) | HPTE_V_BOLTED |
-                       HPTE_V_LARGE | HPTE_V_VALID;
+               hash = (hash << 3) + 7;
+               hp_v = hp0 | ((addr >> 16) & ~0x7fUL);
+               hp_r = hp1 | addr;
+               ret = kvmppc_virtmode_h_enter(vcpu, H_EXACT, hash, hp_v, hp_r);
+               if (ret != H_SUCCESS) {
+                       pr_err("KVM: map_vrma at %lx failed, ret=%ld\n",
+                              addr, ret);
+                       break;
+               }
        }
 }
 
@@ -158,10 +197,814 @@ static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
        kvmppc_set_msr(vcpu, MSR_SF | MSR_ME);
 }
 
+/*
+ * This is called to get a reference to a guest page if there isn't
+ * one already in the kvm->arch.slot_phys[][] arrays.
+ */
+static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
+                                 struct kvm_memory_slot *memslot,
+                                 unsigned long psize)
+{
+       unsigned long start;
+       long np, err;
+       struct page *page, *hpage, *pages[1];
+       unsigned long s, pgsize;
+       unsigned long *physp;
+       unsigned int is_io, got, pgorder;
+       struct vm_area_struct *vma;
+       unsigned long pfn, i, npages;
+
+       physp = kvm->arch.slot_phys[memslot->id];
+       if (!physp)
+               return -EINVAL;
+       if (physp[gfn - memslot->base_gfn])
+               return 0;
+
+       is_io = 0;
+       got = 0;
+       page = NULL;
+       pgsize = psize;
+       err = -EINVAL;
+       start = gfn_to_hva_memslot(memslot, gfn);
+
+       /* Instantiate and get the page we want access to */
+       np = get_user_pages_fast(start, 1, 1, pages);
+       if (np != 1) {
+               /* Look up the vma for the page */
+               down_read(&current->mm->mmap_sem);
+               vma = find_vma(current->mm, start);
+               if (!vma || vma->vm_start > start ||
+                   start + psize > vma->vm_end ||
+                   !(vma->vm_flags & VM_PFNMAP))
+                       goto up_err;
+               is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+               pfn = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+               /* check alignment of pfn vs. requested page size */
+               if (psize > PAGE_SIZE && (pfn & ((psize >> PAGE_SHIFT) - 1)))
+                       goto up_err;
+               up_read(&current->mm->mmap_sem);
+
+       } else {
+               page = pages[0];
+               got = KVMPPC_GOT_PAGE;
+
+               /* See if this is a large page */
+               s = PAGE_SIZE;
+               if (PageHuge(page)) {
+                       hpage = compound_head(page);
+                       s <<= compound_order(hpage);
+                       /* Get the whole large page if slot alignment is ok */
+                       if (s > psize && slot_is_aligned(memslot, s) &&
+                           !(memslot->userspace_addr & (s - 1))) {
+                               start &= ~(s - 1);
+                               pgsize = s;
+                               page = hpage;
+                       }
+               }
+               if (s < psize)
+                       goto out;
+               pfn = page_to_pfn(page);
+       }
+
+       npages = pgsize >> PAGE_SHIFT;
+       pgorder = __ilog2(npages);
+       physp += (gfn - memslot->base_gfn) & ~(npages - 1);
+       spin_lock(&kvm->arch.slot_phys_lock);
+       for (i = 0; i < npages; ++i) {
+               if (!physp[i]) {
+                       physp[i] = ((pfn + i) << PAGE_SHIFT) +
+                               got + is_io + pgorder;
+                       got = 0;
+               }
+       }
+       spin_unlock(&kvm->arch.slot_phys_lock);
+       err = 0;
+
+ out:
+       if (got) {
+               if (PageHuge(page))
+                       page = compound_head(page);
+               put_page(page);
+       }
+       return err;
+
+ up_err:
+       up_read(&current->mm->mmap_sem);
+       return err;
+}
+
+/*
+ * We come here on a H_ENTER call from the guest when we are not
+ * using mmu notifiers and we don't have the requested page pinned
+ * already.
+ */
+long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel)
+{
+       struct kvm *kvm = vcpu->kvm;
+       unsigned long psize, gpa, gfn;
+       struct kvm_memory_slot *memslot;
+       long ret;
+
+       if (kvm->arch.using_mmu_notifiers)
+               goto do_insert;
+
+       psize = hpte_page_size(pteh, ptel);
+       if (!psize)
+               return H_PARAMETER;
+
+       pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
+
+       /* Find the memslot (if any) for this address */
+       gpa = (ptel & HPTE_R_RPN) & ~(psize - 1);
+       gfn = gpa >> PAGE_SHIFT;
+       memslot = gfn_to_memslot(kvm, gfn);
+       if (memslot && !(memslot->flags & KVM_MEMSLOT_INVALID)) {
+               if (!slot_is_aligned(memslot, psize))
+                       return H_PARAMETER;
+               if (kvmppc_get_guest_page(kvm, gfn, memslot, psize) < 0)
+                       return H_PARAMETER;
+       }
+
+ do_insert:
+       /* Protect linux PTE lookup from page table destruction */
+       rcu_read_lock_sched();  /* this disables preemption too */
+       vcpu->arch.pgdir = current->mm->pgd;
+       ret = kvmppc_h_enter(vcpu, flags, pte_index, pteh, ptel);
+       rcu_read_unlock_sched();
+       if (ret == H_TOO_HARD) {
+               /* this can't happen */
+               pr_err("KVM: Oops, kvmppc_h_enter returned too hard!\n");
+               ret = H_RESOURCE;       /* or something */
+       }
+       return ret;
+
+}
+
+static struct kvmppc_slb *kvmppc_mmu_book3s_hv_find_slbe(struct kvm_vcpu *vcpu,
+                                                        gva_t eaddr)
+{
+       u64 mask;
+       int i;
+
+       for (i = 0; i < vcpu->arch.slb_nr; i++) {
+               if (!(vcpu->arch.slb[i].orige & SLB_ESID_V))
+                       continue;
+
+               if (vcpu->arch.slb[i].origv & SLB_VSID_B_1T)
+                       mask = ESID_MASK_1T;
+               else
+                       mask = ESID_MASK;
+
+               if (((vcpu->arch.slb[i].orige ^ eaddr) & mask) == 0)
+                       return &vcpu->arch.slb[i];
+       }
+       return NULL;
+}
+
+static unsigned long kvmppc_mmu_get_real_addr(unsigned long v, unsigned long r,
+                       unsigned long ea)
+{
+       unsigned long ra_mask;
+
+       ra_mask = hpte_page_size(v, r) - 1;
+       return (r & HPTE_R_RPN & ~ra_mask) | (ea & ra_mask);
+}
+
 static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
-                               struct kvmppc_pte *gpte, bool data)
+                       struct kvmppc_pte *gpte, bool data)
+{
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_slb *slbe;
+       unsigned long slb_v;
+       unsigned long pp, key;
+       unsigned long v, gr;
+       unsigned long *hptep;
+       int index;
+       int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
+
+       /* Get SLB entry */
+       if (virtmode) {
+               slbe = kvmppc_mmu_book3s_hv_find_slbe(vcpu, eaddr);
+               if (!slbe)
+                       return -EINVAL;
+               slb_v = slbe->origv;
+       } else {
+               /* real mode access */
+               slb_v = vcpu->kvm->arch.vrma_slb_v;
+       }
+
+       /* Find the HPTE in the hash table */
+       index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
+                                        HPTE_V_VALID | HPTE_V_ABSENT);
+       if (index < 0)
+               return -ENOENT;
+       hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+       v = hptep[0] & ~HPTE_V_HVLOCK;
+       gr = kvm->arch.revmap[index].guest_rpte;
+
+       /* Unlock the HPTE */
+       asm volatile("lwsync" : : : "memory");
+       hptep[0] = v;
+
+       gpte->eaddr = eaddr;
+       gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
+
+       /* Get PP bits and key for permission check */
+       pp = gr & (HPTE_R_PP0 | HPTE_R_PP);
+       key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
+       key &= slb_v;
+
+       /* Calculate permissions */
+       gpte->may_read = hpte_read_permission(pp, key);
+       gpte->may_write = hpte_write_permission(pp, key);
+       gpte->may_execute = gpte->may_read && !(gr & (HPTE_R_N | HPTE_R_G));
+
+       /* Storage key permission check for POWER7 */
+       if (data && virtmode && cpu_has_feature(CPU_FTR_ARCH_206)) {
+               int amrfield = hpte_get_skey_perm(gr, vcpu->arch.amr);
+               if (amrfield & 1)
+                       gpte->may_read = 0;
+               if (amrfield & 2)
+                       gpte->may_write = 0;
+       }
+
+       /* Get the guest physical address */
+       gpte->raddr = kvmppc_mmu_get_real_addr(v, gr, eaddr);
+       return 0;
+}
+
+/*
+ * Quick test for whether an instruction is a load or a store.
+ * If the instruction is a load or a store, then this will indicate
+ * which it is, at least on server processors.  (Embedded processors
+ * have some external PID instructions that don't follow the rule
+ * embodied here.)  If the instruction isn't a load or store, then
+ * this doesn't return anything useful.
+ */
+static int instruction_is_store(unsigned int instr)
+{
+       unsigned int mask;
+
+       mask = 0x10000000;
+       if ((instr & 0xfc000000) == 0x7c000000)
+               mask = 0x100;           /* major opcode 31 */
+       return (instr & mask) != 0;
+}
+
+static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                                 unsigned long gpa, int is_store)
+{
+       int ret;
+       u32 last_inst;
+       unsigned long srr0 = kvmppc_get_pc(vcpu);
+
+       /* We try to load the last instruction.  We don't let
+        * emulate_instruction do it as it doesn't check what
+        * kvmppc_ld returns.
+        * If we fail, we just return to the guest and try executing it again.
+        */
+       if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) {
+               ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
+               if (ret != EMULATE_DONE || last_inst == KVM_INST_FETCH_FAILED)
+                       return RESUME_GUEST;
+               vcpu->arch.last_inst = last_inst;
+       }
+
+       /*
+        * WARNING: We do not know for sure whether the instruction we just
+        * read from memory is the same that caused the fault in the first
+        * place.  If the instruction we read is neither an load or a store,
+        * then it can't access memory, so we don't need to worry about
+        * enforcing access permissions.  So, assuming it is a load or
+        * store, we just check that its direction (load or store) is
+        * consistent with the original fault, since that's what we
+        * checked the access permissions against.  If there is a mismatch
+        * we just return and retry the instruction.
+        */
+
+       if (instruction_is_store(vcpu->arch.last_inst) != !!is_store)
+               return RESUME_GUEST;
+
+       /*
+        * Emulated accesses are emulated by looking at the hash for
+        * translation once, then performing the access later. The
+        * translation could be invalidated in the meantime in which
+        * point performing the subsequent memory access on the old
+        * physical address could possibly be a security hole for the
+        * guest (but not the host).
+        *
+        * This is less of an issue for MMIO stores since they aren't
+        * globally visible. It could be an issue for MMIO loads to
+        * a certain extent but we'll ignore it for now.
+        */
+
+       vcpu->arch.paddr_accessed = gpa;
+       return kvmppc_emulate_mmio(run, vcpu);
+}
+
+int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                               unsigned long ea, unsigned long dsisr)
+{
+       struct kvm *kvm = vcpu->kvm;
+       unsigned long *hptep, hpte[3], r;
+       unsigned long mmu_seq, psize, pte_size;
+       unsigned long gfn, hva, pfn;
+       struct kvm_memory_slot *memslot;
+       unsigned long *rmap;
+       struct revmap_entry *rev;
+       struct page *page, *pages[1];
+       long index, ret, npages;
+       unsigned long is_io;
+       unsigned int writing, write_ok;
+       struct vm_area_struct *vma;
+       unsigned long rcbits;
+
+       /*
+        * Real-mode code has already searched the HPT and found the
+        * entry we're interested in.  Lock the entry and check that
+        * it hasn't changed.  If it has, just return and re-execute the
+        * instruction.
+        */
+       if (ea != vcpu->arch.pgfault_addr)
+               return RESUME_GUEST;
+       index = vcpu->arch.pgfault_index;
+       hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+       rev = &kvm->arch.revmap[index];
+       preempt_disable();
+       while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
+               cpu_relax();
+       hpte[0] = hptep[0] & ~HPTE_V_HVLOCK;
+       hpte[1] = hptep[1];
+       hpte[2] = r = rev->guest_rpte;
+       asm volatile("lwsync" : : : "memory");
+       hptep[0] = hpte[0];
+       preempt_enable();
+
+       if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
+           hpte[1] != vcpu->arch.pgfault_hpte[1])
+               return RESUME_GUEST;
+
+       /* Translate the logical address and get the page */
+       psize = hpte_page_size(hpte[0], r);
+       gfn = hpte_rpn(r, psize);
+       memslot = gfn_to_memslot(kvm, gfn);
+
+       /* No memslot means it's an emulated MMIO region */
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
+               unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
+               return kvmppc_hv_emulate_mmio(run, vcpu, gpa,
+                                             dsisr & DSISR_ISSTORE);
+       }
+
+       if (!kvm->arch.using_mmu_notifiers)
+               return -EFAULT;         /* should never get here */
+
+       /* used to check for invalidations in progress */
+       mmu_seq = kvm->mmu_notifier_seq;
+       smp_rmb();
+
+       is_io = 0;
+       pfn = 0;
+       page = NULL;
+       pte_size = PAGE_SIZE;
+       writing = (dsisr & DSISR_ISSTORE) != 0;
+       /* If writing != 0, then the HPTE must allow writing, if we get here */
+       write_ok = writing;
+       hva = gfn_to_hva_memslot(memslot, gfn);
+       npages = get_user_pages_fast(hva, 1, writing, pages);
+       if (npages < 1) {
+               /* Check if it's an I/O mapping */
+               down_read(&current->mm->mmap_sem);
+               vma = find_vma(current->mm, hva);
+               if (vma && vma->vm_start <= hva && hva + psize <= vma->vm_end &&
+                   (vma->vm_flags & VM_PFNMAP)) {
+                       pfn = vma->vm_pgoff +
+                               ((hva - vma->vm_start) >> PAGE_SHIFT);
+                       pte_size = psize;
+                       is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+                       write_ok = vma->vm_flags & VM_WRITE;
+               }
+               up_read(&current->mm->mmap_sem);
+               if (!pfn)
+                       return -EFAULT;
+       } else {
+               page = pages[0];
+               if (PageHuge(page)) {
+                       page = compound_head(page);
+                       pte_size <<= compound_order(page);
+               }
+               /* if the guest wants write access, see if that is OK */
+               if (!writing && hpte_is_writable(r)) {
+                       pte_t *ptep, pte;
+
+                       /*
+                        * We need to protect against page table destruction
+                        * while looking up and updating the pte.
+                        */
+                       rcu_read_lock_sched();
+                       ptep = find_linux_pte_or_hugepte(current->mm->pgd,
+                                                        hva, NULL);
+                       if (ptep && pte_present(*ptep)) {
+                               pte = kvmppc_read_update_linux_pte(ptep, 1);
+                               if (pte_write(pte))
+                                       write_ok = 1;
+                       }
+                       rcu_read_unlock_sched();
+               }
+               pfn = page_to_pfn(page);
+       }
+
+       ret = -EFAULT;
+       if (psize > pte_size)
+               goto out_put;
+
+       /* Check WIMG vs. the actual page we're accessing */
+       if (!hpte_cache_flags_ok(r, is_io)) {
+               if (is_io)
+                       return -EFAULT;
+               /*
+                * Allow guest to map emulated device memory as
+                * uncacheable, but actually make it cacheable.
+                */
+               r = (r & ~(HPTE_R_W|HPTE_R_I|HPTE_R_G)) | HPTE_R_M;
+       }
+
+       /* Set the HPTE to point to pfn */
+       r = (r & ~(HPTE_R_PP0 - pte_size)) | (pfn << PAGE_SHIFT);
+       if (hpte_is_writable(r) && !write_ok)
+               r = hpte_make_readonly(r);
+       ret = RESUME_GUEST;
+       preempt_disable();
+       while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
+               cpu_relax();
+       if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
+           rev->guest_rpte != hpte[2])
+               /* HPTE has been changed under us; let the guest retry */
+               goto out_unlock;
+       hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
+
+       rmap = &memslot->rmap[gfn - memslot->base_gfn];
+       lock_rmap(rmap);
+
+       /* Check if we might have been invalidated; let the guest retry if so */
+       ret = RESUME_GUEST;
+       if (mmu_notifier_retry(vcpu, mmu_seq)) {
+               unlock_rmap(rmap);
+               goto out_unlock;
+       }
+
+       /* Only set R/C in real HPTE if set in both *rmap and guest_rpte */
+       rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
+       r &= rcbits | ~(HPTE_R_R | HPTE_R_C);
+
+       if (hptep[0] & HPTE_V_VALID) {
+               /* HPTE was previously valid, so we need to invalidate it */
+               unlock_rmap(rmap);
+               hptep[0] |= HPTE_V_ABSENT;
+               kvmppc_invalidate_hpte(kvm, hptep, index);
+               /* don't lose previous R and C bits */
+               r |= hptep[1] & (HPTE_R_R | HPTE_R_C);
+       } else {
+               kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
+       }
+
+       hptep[1] = r;
+       eieio();
+       hptep[0] = hpte[0];
+       asm volatile("ptesync" : : : "memory");
+       preempt_enable();
+       if (page && hpte_is_writable(r))
+               SetPageDirty(page);
+
+ out_put:
+       if (page)
+               put_page(page);
+       return ret;
+
+ out_unlock:
+       hptep[0] &= ~HPTE_V_HVLOCK;
+       preempt_enable();
+       goto out_put;
+}
+
+static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
+                         int (*handler)(struct kvm *kvm, unsigned long *rmapp,
+                                        unsigned long gfn))
+{
+       int ret;
+       int retval = 0;
+       struct kvm_memslots *slots;
+       struct kvm_memory_slot *memslot;
+
+       slots = kvm_memslots(kvm);
+       kvm_for_each_memslot(memslot, slots) {
+               unsigned long start = memslot->userspace_addr;
+               unsigned long end;
+
+               end = start + (memslot->npages << PAGE_SHIFT);
+               if (hva >= start && hva < end) {
+                       gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
+
+                       ret = handler(kvm, &memslot->rmap[gfn_offset],
+                                     memslot->base_gfn + gfn_offset);
+                       retval |= ret;
+               }
+       }
+
+       return retval;
+}
+
+static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                          unsigned long gfn)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long h, i, j;
+       unsigned long *hptep;
+       unsigned long ptel, psize, rcbits;
+
+       for (;;) {
+               lock_rmap(rmapp);
+               if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+                       unlock_rmap(rmapp);
+                       break;
+               }
+
+               /*
+                * To avoid an ABBA deadlock with the HPTE lock bit,
+                * we can't spin on the HPTE lock while holding the
+                * rmap chain lock.
+                */
+               i = *rmapp & KVMPPC_RMAP_INDEX;
+               hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+               if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
+                       /* unlock rmap before spinning on the HPTE lock */
+                       unlock_rmap(rmapp);
+                       while (hptep[0] & HPTE_V_HVLOCK)
+                               cpu_relax();
+                       continue;
+               }
+               j = rev[i].forw;
+               if (j == i) {
+                       /* chain is now empty */
+                       *rmapp &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX);
+               } else {
+                       /* remove i from chain */
+                       h = rev[i].back;
+                       rev[h].forw = j;
+                       rev[j].back = h;
+                       rev[i].forw = rev[i].back = i;
+                       *rmapp = (*rmapp & ~KVMPPC_RMAP_INDEX) | j;
+               }
+
+               /* Now check and modify the HPTE */
+               ptel = rev[i].guest_rpte;
+               psize = hpte_page_size(hptep[0], ptel);
+               if ((hptep[0] & HPTE_V_VALID) &&
+                   hpte_rpn(ptel, psize) == gfn) {
+                       hptep[0] |= HPTE_V_ABSENT;
+                       kvmppc_invalidate_hpte(kvm, hptep, i);
+                       /* Harvest R and C */
+                       rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
+                       *rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
+                       rev[i].guest_rpte = ptel | rcbits;
+               }
+               unlock_rmap(rmapp);
+               hptep[0] &= ~HPTE_V_HVLOCK;
+       }
+       return 0;
+}
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       if (kvm->arch.using_mmu_notifiers)
+               kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
+       return 0;
+}
+
+static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                        unsigned long gfn)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long head, i, j;
+       unsigned long *hptep;
+       int ret = 0;
+
+ retry:
+       lock_rmap(rmapp);
+       if (*rmapp & KVMPPC_RMAP_REFERENCED) {
+               *rmapp &= ~KVMPPC_RMAP_REFERENCED;
+               ret = 1;
+       }
+       if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+               unlock_rmap(rmapp);
+               return ret;
+       }
+
+       i = head = *rmapp & KVMPPC_RMAP_INDEX;
+       do {
+               hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+               j = rev[i].forw;
+
+               /* If this HPTE isn't referenced, ignore it */
+               if (!(hptep[1] & HPTE_R_R))
+                       continue;
+
+               if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
+                       /* unlock rmap before spinning on the HPTE lock */
+                       unlock_rmap(rmapp);
+                       while (hptep[0] & HPTE_V_HVLOCK)
+                               cpu_relax();
+                       goto retry;
+               }
+
+               /* Now check and modify the HPTE */
+               if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) {
+                       kvmppc_clear_ref_hpte(kvm, hptep, i);
+                       rev[i].guest_rpte |= HPTE_R_R;
+                       ret = 1;
+               }
+               hptep[0] &= ~HPTE_V_HVLOCK;
+       } while ((i = j) != head);
+
+       unlock_rmap(rmapp);
+       return ret;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       if (!kvm->arch.using_mmu_notifiers)
+               return 0;
+       return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
+}
+
+static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                             unsigned long gfn)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long head, i, j;
+       unsigned long *hp;
+       int ret = 1;
+
+       if (*rmapp & KVMPPC_RMAP_REFERENCED)
+               return 1;
+
+       lock_rmap(rmapp);
+       if (*rmapp & KVMPPC_RMAP_REFERENCED)
+               goto out;
+
+       if (*rmapp & KVMPPC_RMAP_PRESENT) {
+               i = head = *rmapp & KVMPPC_RMAP_INDEX;
+               do {
+                       hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4));
+                       j = rev[i].forw;
+                       if (hp[1] & HPTE_R_R)
+                               goto out;
+               } while ((i = j) != head);
+       }
+       ret = 0;
+
+ out:
+       unlock_rmap(rmapp);
+       return ret;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       if (!kvm->arch.using_mmu_notifiers)
+               return 0;
+       return kvm_handle_hva(kvm, hva, kvm_test_age_rmapp);
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
 {
-       return -ENOENT;
+       if (!kvm->arch.using_mmu_notifiers)
+               return;
+       kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
+}
+
+static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long head, i, j;
+       unsigned long *hptep;
+       int ret = 0;
+
+ retry:
+       lock_rmap(rmapp);
+       if (*rmapp & KVMPPC_RMAP_CHANGED) {
+               *rmapp &= ~KVMPPC_RMAP_CHANGED;
+               ret = 1;
+       }
+       if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+               unlock_rmap(rmapp);
+               return ret;
+       }
+
+       i = head = *rmapp & KVMPPC_RMAP_INDEX;
+       do {
+               hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+               j = rev[i].forw;
+
+               if (!(hptep[1] & HPTE_R_C))
+                       continue;
+
+               if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
+                       /* unlock rmap before spinning on the HPTE lock */
+                       unlock_rmap(rmapp);
+                       while (hptep[0] & HPTE_V_HVLOCK)
+                               cpu_relax();
+                       goto retry;
+               }
+
+               /* Now check and modify the HPTE */
+               if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_C)) {
+                       /* need to make it temporarily absent to clear C */
+                       hptep[0] |= HPTE_V_ABSENT;
+                       kvmppc_invalidate_hpte(kvm, hptep, i);
+                       hptep[1] &= ~HPTE_R_C;
+                       eieio();
+                       hptep[0] = (hptep[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
+                       rev[i].guest_rpte |= HPTE_R_C;
+                       ret = 1;
+               }
+               hptep[0] &= ~HPTE_V_HVLOCK;
+       } while ((i = j) != head);
+
+       unlock_rmap(rmapp);
+       return ret;
+}
+
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+       unsigned long i;
+       unsigned long *rmapp, *map;
+
+       preempt_disable();
+       rmapp = memslot->rmap;
+       map = memslot->dirty_bitmap;
+       for (i = 0; i < memslot->npages; ++i) {
+               if (kvm_test_clear_dirty(kvm, rmapp))
+                       __set_bit_le(i, map);
+               ++rmapp;
+       }
+       preempt_enable();
+       return 0;
+}
+
+void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
+                           unsigned long *nb_ret)
+{
+       struct kvm_memory_slot *memslot;
+       unsigned long gfn = gpa >> PAGE_SHIFT;
+       struct page *page, *pages[1];
+       int npages;
+       unsigned long hva, psize, offset;
+       unsigned long pa;
+       unsigned long *physp;
+
+       memslot = gfn_to_memslot(kvm, gfn);
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+               return NULL;
+       if (!kvm->arch.using_mmu_notifiers) {
+               physp = kvm->arch.slot_phys[memslot->id];
+               if (!physp)
+                       return NULL;
+               physp += gfn - memslot->base_gfn;
+               pa = *physp;
+               if (!pa) {
+                       if (kvmppc_get_guest_page(kvm, gfn, memslot,
+                                                 PAGE_SIZE) < 0)
+                               return NULL;
+                       pa = *physp;
+               }
+               page = pfn_to_page(pa >> PAGE_SHIFT);
+       } else {
+               hva = gfn_to_hva_memslot(memslot, gfn);
+               npages = get_user_pages_fast(hva, 1, 1, pages);
+               if (npages < 1)
+                       return NULL;
+               page = pages[0];
+       }
+       psize = PAGE_SIZE;
+       if (PageHuge(page)) {
+               page = compound_head(page);
+               psize <<= compound_order(page);
+       }
+       if (!kvm->arch.using_mmu_notifiers)
+               get_page(page);
+       offset = gpa & (psize - 1);
+       if (nb_ret)
+               *nb_ret = psize - offset;
+       return page_address(page) + offset;
+}
+
+void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
+{
+       struct page *page = virt_to_page(va);
+
+       page = compound_head(page);
+       put_page(page);
 }
 
 void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
index 0c9dc62532d02c78c2480d569fc014cb637713b1..f1950d1318273ae3b8dd2455ee493d436a7aaef8 100644 (file)
@@ -230,9 +230,12 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
                        r = kvmppc_st(vcpu, &addr, 32, zeros, true);
                        if ((r == -ENOENT) || (r == -EPERM)) {
+                               struct kvmppc_book3s_shadow_vcpu *svcpu;
+
+                               svcpu = svcpu_get(vcpu);
                                *advance = 0;
                                vcpu->arch.shared->dar = vaddr;
-                               to_svcpu(vcpu)->fault_dar = vaddr;
+                               svcpu->fault_dar = vaddr;
 
                                dsisr = DSISR_ISSTORE;
                                if (r == -ENOENT)
@@ -241,7 +244,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                        dsisr |= DSISR_PROTFAULT;
 
                                vcpu->arch.shared->dsisr = dsisr;
-                               to_svcpu(vcpu)->fault_dsisr = dsisr;
+                               svcpu->fault_dsisr = dsisr;
+                               svcpu_put(svcpu);
 
                                kvmppc_book3s_queue_irqprio(vcpu,
                                        BOOK3S_INTERRUPT_DATA_STORAGE);
index a7267167a55040c1e7b9acbdeb4d6fcc2764dfad..01294a5099dda77b3528cfce18eef9dc78ff13ab 100644 (file)
 #include <asm/cputhreads.h>
 #include <asm/page.h>
 #include <asm/hvcall.h>
+#include <asm/switch_to.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
-
-/*
- * For now, limit memory to 64GB and require it to be large pages.
- * This value is chosen because it makes the ram_pginfo array be
- * 64kB in size, which is about as large as we want to be trying
- * to allocate with kmalloc.
- */
-#define MAX_MEM_ORDER          36
-
-#define LARGE_PAGE_ORDER       24      /* 16MB pages */
+#include <linux/hugetlb.h>
 
 /* #define EXIT_DEBUG */
 /* #define EXIT_DEBUG_SIMPLE */
 /* #define EXIT_DEBUG_INT */
 
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
+static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu);
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
@@ -146,10 +139,10 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
                                       unsigned long vcpuid, unsigned long vpa)
 {
        struct kvm *kvm = vcpu->kvm;
-       unsigned long pg_index, ra, len;
-       unsigned long pg_offset;
+       unsigned long len, nb;
        void *va;
        struct kvm_vcpu *tvcpu;
+       int err = H_PARAMETER;
 
        tvcpu = kvmppc_find_vcpu(kvm, vcpuid);
        if (!tvcpu)
@@ -162,45 +155,41 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
        if (flags < 4) {
                if (vpa & 0x7f)
                        return H_PARAMETER;
+               if (flags >= 2 && !tvcpu->arch.vpa)
+                       return H_RESOURCE;
                /* registering new area; convert logical addr to real */
-               pg_index = vpa >> kvm->arch.ram_porder;
-               pg_offset = vpa & (kvm->arch.ram_psize - 1);
-               if (pg_index >= kvm->arch.ram_npages)
+               va = kvmppc_pin_guest_page(kvm, vpa, &nb);
+               if (va == NULL)
                        return H_PARAMETER;
-               if (kvm->arch.ram_pginfo[pg_index].pfn == 0)
-                       return H_PARAMETER;
-               ra = kvm->arch.ram_pginfo[pg_index].pfn << PAGE_SHIFT;
-               ra |= pg_offset;
-               va = __va(ra);
                if (flags <= 1)
                        len = *(unsigned short *)(va + 4);
                else
                        len = *(unsigned int *)(va + 4);
-               if (pg_offset + len > kvm->arch.ram_psize)
-                       return H_PARAMETER;
+               if (len > nb)
+                       goto out_unpin;
                switch (flags) {
                case 1:         /* register VPA */
                        if (len < 640)
-                               return H_PARAMETER;
+                               goto out_unpin;
+                       if (tvcpu->arch.vpa)
+                               kvmppc_unpin_guest_page(kvm, vcpu->arch.vpa);
                        tvcpu->arch.vpa = va;
                        init_vpa(vcpu, va);
                        break;
                case 2:         /* register DTL */
                        if (len < 48)
-                               return H_PARAMETER;
-                       if (!tvcpu->arch.vpa)
-                               return H_RESOURCE;
+                               goto out_unpin;
                        len -= len % 48;
+                       if (tvcpu->arch.dtl)
+                               kvmppc_unpin_guest_page(kvm, vcpu->arch.dtl);
                        tvcpu->arch.dtl = va;
                        tvcpu->arch.dtl_end = va + len;
                        break;
                case 3:         /* register SLB shadow buffer */
-                       if (len < 8)
-                               return H_PARAMETER;
-                       if (!tvcpu->arch.vpa)
-                               return H_RESOURCE;
-                       tvcpu->arch.slb_shadow = va;
-                       len = (len - 16) / 16;
+                       if (len < 16)
+                               goto out_unpin;
+                       if (tvcpu->arch.slb_shadow)
+                               kvmppc_unpin_guest_page(kvm, vcpu->arch.slb_shadow);
                        tvcpu->arch.slb_shadow = va;
                        break;
                }
@@ -209,17 +198,30 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
                case 5:         /* unregister VPA */
                        if (tvcpu->arch.slb_shadow || tvcpu->arch.dtl)
                                return H_RESOURCE;
+                       if (!tvcpu->arch.vpa)
+                               break;
+                       kvmppc_unpin_guest_page(kvm, tvcpu->arch.vpa);
                        tvcpu->arch.vpa = NULL;
                        break;
                case 6:         /* unregister DTL */
+                       if (!tvcpu->arch.dtl)
+                               break;
+                       kvmppc_unpin_guest_page(kvm, tvcpu->arch.dtl);
                        tvcpu->arch.dtl = NULL;
                        break;
                case 7:         /* unregister SLB shadow buffer */
+                       if (!tvcpu->arch.slb_shadow)
+                               break;
+                       kvmppc_unpin_guest_page(kvm, tvcpu->arch.slb_shadow);
                        tvcpu->arch.slb_shadow = NULL;
                        break;
                }
        }
        return H_SUCCESS;
+
+ out_unpin:
+       kvmppc_unpin_guest_page(kvm, va);
+       return err;
 }
 
 int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
@@ -229,6 +231,12 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        struct kvm_vcpu *tvcpu;
 
        switch (req) {
+       case H_ENTER:
+               ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
+                                             kvmppc_get_gpr(vcpu, 5),
+                                             kvmppc_get_gpr(vcpu, 6),
+                                             kvmppc_get_gpr(vcpu, 7));
+               break;
        case H_CEDE:
                break;
        case H_PROD:
@@ -318,20 +326,19 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                break;
        }
        /*
-        * We get these next two if the guest does a bad real-mode access,
-        * as we have enabled VRMA (virtualized real mode area) mode in the
-        * LPCR.  We just generate an appropriate DSI/ISI to the guest.
+        * We get these next two if the guest accesses a page which it thinks
+        * it has mapped but which is not actually present, either because
+        * it is for an emulated I/O device or because the corresonding
+        * host page has been paged out.  Any other HDSI/HISI interrupts
+        * have been handled already.
         */
        case BOOK3S_INTERRUPT_H_DATA_STORAGE:
-               vcpu->arch.shregs.dsisr = vcpu->arch.fault_dsisr;
-               vcpu->arch.shregs.dar = vcpu->arch.fault_dar;
-               kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
-               r = RESUME_GUEST;
+               r = kvmppc_book3s_hv_page_fault(run, vcpu,
+                               vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
                break;
        case BOOK3S_INTERRUPT_H_INST_STORAGE:
-               kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE,
-                                       0x08000000);
-               r = RESUME_GUEST;
+               r = kvmppc_book3s_hv_page_fault(run, vcpu,
+                               kvmppc_get_pc(vcpu), 0);
                break;
        /*
         * This occurs if the guest executes an illegal instruction.
@@ -391,6 +398,42 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = put_user(0, (u64 __user *)reg->addr);
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+       {
+               u64 hior;
+               /* Only allow this to be set to zero */
+               r = get_user(hior, (u64 __user *)reg->addr);
+               if (!r && (hior != 0))
+                       r = -EINVAL;
+               break;
+       }
+       default:
+               break;
+       }
+
+       return r;
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
        if (cpu_has_feature(CPU_FTR_HVMODE))
@@ -410,7 +453,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
                goto out;
 
        err = -ENOMEM;
-       vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+       vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
        if (!vcpu)
                goto out;
 
@@ -462,15 +505,21 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
        return vcpu;
 
 free_vcpu:
-       kfree(vcpu);
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
 out:
        return ERR_PTR(err);
 }
 
 void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 {
+       if (vcpu->arch.dtl)
+               kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.dtl);
+       if (vcpu->arch.slb_shadow)
+               kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.slb_shadow);
+       if (vcpu->arch.vpa)
+               kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.vpa);
        kvm_vcpu_uninit(vcpu);
-       kfree(vcpu);
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
 
 static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
@@ -481,7 +530,7 @@ static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
        if (now > vcpu->arch.dec_expires) {
                /* decrementer has already gone negative */
                kvmppc_core_queue_dec(vcpu);
-               kvmppc_core_deliver_interrupts(vcpu);
+               kvmppc_core_prepare_to_enter(vcpu);
                return;
        }
        dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC
@@ -796,7 +845,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
                list_for_each_entry_safe(v, vn, &vc->runnable_threads,
                                         arch.run_list) {
-                       kvmppc_core_deliver_interrupts(v);
+                       kvmppc_core_prepare_to_enter(v);
                        if (signal_pending(v->arch.run_task)) {
                                kvmppc_remove_runnable(vc, v);
                                v->stat.signal_exits++;
@@ -835,20 +884,26 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
                return -EINVAL;
        }
 
+       kvmppc_core_prepare_to_enter(vcpu);
+
        /* No need to go into the guest when all we'll do is come back out */
        if (signal_pending(current)) {
                run->exit_reason = KVM_EXIT_INTR;
                return -EINTR;
        }
 
-       /* On PPC970, check that we have an RMA region */
-       if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
-               return -EPERM;
+       /* On the first time here, set up VRMA or RMA */
+       if (!vcpu->kvm->arch.rma_setup_done) {
+               r = kvmppc_hv_setup_rma(vcpu);
+               if (r)
+                       return r;
+       }
 
        flush_fp_to_thread(current);
        flush_altivec_to_thread(current);
        flush_vsx_to_thread(current);
        vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+       vcpu->arch.pgdir = current->mm->pgd;
 
        do {
                r = kvmppc_run_vcpu(run, vcpu);
@@ -856,7 +911,7 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
                if (run->exit_reason == KVM_EXIT_PAPR_HCALL &&
                    !(vcpu->arch.shregs.msr & MSR_PR)) {
                        r = kvmppc_pseries_do_hcall(vcpu);
-                       kvmppc_core_deliver_interrupts(vcpu);
+                       kvmppc_core_prepare_to_enter(vcpu);
                }
        } while (r == RESUME_GUEST);
        return r;
@@ -1000,7 +1055,7 @@ static inline int lpcr_rmls(unsigned long rma_size)
 
 static int kvm_rma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-       struct kvmppc_rma_info *ri = vma->vm_file->private_data;
+       struct kvmppc_linear_info *ri = vma->vm_file->private_data;
        struct page *page;
 
        if (vmf->pgoff >= ri->npages)
@@ -1025,7 +1080,7 @@ static int kvm_rma_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int kvm_rma_release(struct inode *inode, struct file *filp)
 {
-       struct kvmppc_rma_info *ri = filp->private_data;
+       struct kvmppc_linear_info *ri = filp->private_data;
 
        kvm_release_rma(ri);
        return 0;
@@ -1038,7 +1093,7 @@ static struct file_operations kvm_rma_fops = {
 
 long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
 {
-       struct kvmppc_rma_info *ri;
+       struct kvmppc_linear_info *ri;
        long fd;
 
        ri = kvm_alloc_rma();
@@ -1053,89 +1108,189 @@ long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
        return fd;
 }
 
-static struct page *hva_to_page(unsigned long addr)
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 {
-       struct page *page[1];
-       int npages;
+       struct kvm_memory_slot *memslot;
+       int r;
+       unsigned long n;
 
-       might_sleep();
+       mutex_lock(&kvm->slots_lock);
 
-       npages = get_user_pages_fast(addr, 1, 1, page);
+       r = -EINVAL;
+       if (log->slot >= KVM_MEMORY_SLOTS)
+               goto out;
 
-       if (unlikely(npages != 1))
-               return 0;
+       memslot = id_to_memslot(kvm->memslots, log->slot);
+       r = -ENOENT;
+       if (!memslot->dirty_bitmap)
+               goto out;
+
+       n = kvm_dirty_bitmap_bytes(memslot);
+       memset(memslot->dirty_bitmap, 0, n);
+
+       r = kvmppc_hv_get_dirty_log(kvm, memslot);
+       if (r)
+               goto out;
 
-       return page[0];
+       r = -EFAULT;
+       if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
+               goto out;
+
+       r = 0;
+out:
+       mutex_unlock(&kvm->slots_lock);
+       return r;
+}
+
+static unsigned long slb_pgsize_encoding(unsigned long psize)
+{
+       unsigned long senc = 0;
+
+       if (psize > 0x1000) {
+               senc = SLB_VSID_L;
+               if (psize == 0x10000)
+                       senc |= SLB_VSID_LP_01;
+       }
+       return senc;
 }
 
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
                                struct kvm_userspace_memory_region *mem)
 {
-       unsigned long psize, porder;
-       unsigned long i, npages, totalpages;
-       unsigned long pg_ix;
-       struct kvmppc_pginfo *pginfo;
-       unsigned long hva;
-       struct kvmppc_rma_info *ri = NULL;
+       unsigned long npages;
+       unsigned long *phys;
+
+       /* Allocate a slot_phys array */
+       phys = kvm->arch.slot_phys[mem->slot];
+       if (!kvm->arch.using_mmu_notifiers && !phys) {
+               npages = mem->memory_size >> PAGE_SHIFT;
+               phys = vzalloc(npages * sizeof(unsigned long));
+               if (!phys)
+                       return -ENOMEM;
+               kvm->arch.slot_phys[mem->slot] = phys;
+               kvm->arch.slot_npages[mem->slot] = npages;
+       }
+
+       return 0;
+}
+
+static void unpin_slot(struct kvm *kvm, int slot_id)
+{
+       unsigned long *physp;
+       unsigned long j, npages, pfn;
        struct page *page;
 
-       /* For now, only allow 16MB pages */
-       porder = LARGE_PAGE_ORDER;
-       psize = 1ul << porder;
-       if ((mem->memory_size & (psize - 1)) ||
-           (mem->guest_phys_addr & (psize - 1))) {
-               pr_err("bad memory_size=%llx @ %llx\n",
-                      mem->memory_size, mem->guest_phys_addr);
-               return -EINVAL;
+       physp = kvm->arch.slot_phys[slot_id];
+       npages = kvm->arch.slot_npages[slot_id];
+       if (physp) {
+               spin_lock(&kvm->arch.slot_phys_lock);
+               for (j = 0; j < npages; j++) {
+                       if (!(physp[j] & KVMPPC_GOT_PAGE))
+                               continue;
+                       pfn = physp[j] >> PAGE_SHIFT;
+                       page = pfn_to_page(pfn);
+                       if (PageHuge(page))
+                               page = compound_head(page);
+                       SetPageDirty(page);
+                       put_page(page);
+               }
+               kvm->arch.slot_phys[slot_id] = NULL;
+               spin_unlock(&kvm->arch.slot_phys_lock);
+               vfree(physp);
        }
+}
 
-       npages = mem->memory_size >> porder;
-       totalpages = (mem->guest_phys_addr + mem->memory_size) >> porder;
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+                               struct kvm_userspace_memory_region *mem)
+{
+}
 
-       /* More memory than we have space to track? */
-       if (totalpages > (1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER)))
-               return -EINVAL;
+static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu)
+{
+       int err = 0;
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_linear_info *ri = NULL;
+       unsigned long hva;
+       struct kvm_memory_slot *memslot;
+       struct vm_area_struct *vma;
+       unsigned long lpcr, senc;
+       unsigned long psize, porder;
+       unsigned long rma_size;
+       unsigned long rmls;
+       unsigned long *physp;
+       unsigned long i, npages;
 
-       /* Do we already have an RMA registered? */
-       if (mem->guest_phys_addr == 0 && kvm->arch.rma)
-               return -EINVAL;
+       mutex_lock(&kvm->lock);
+       if (kvm->arch.rma_setup_done)
+               goto out;       /* another vcpu beat us to it */
 
-       if (totalpages > kvm->arch.ram_npages)
-               kvm->arch.ram_npages = totalpages;
+       /* Look up the memslot for guest physical address 0 */
+       memslot = gfn_to_memslot(kvm, 0);
+
+       /* We must have some memory at 0 by now */
+       err = -EINVAL;
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+               goto out;
+
+       /* Look up the VMA for the start of this memory slot */
+       hva = memslot->userspace_addr;
+       down_read(&current->mm->mmap_sem);
+       vma = find_vma(current->mm, hva);
+       if (!vma || vma->vm_start > hva || (vma->vm_flags & VM_IO))
+               goto up_out;
+
+       psize = vma_kernel_pagesize(vma);
+       porder = __ilog2(psize);
 
        /* Is this one of our preallocated RMAs? */
-       if (mem->guest_phys_addr == 0) {
-               struct vm_area_struct *vma;
-
-               down_read(&current->mm->mmap_sem);
-               vma = find_vma(current->mm, mem->userspace_addr);
-               if (vma && vma->vm_file &&
-                   vma->vm_file->f_op == &kvm_rma_fops &&
-                   mem->userspace_addr == vma->vm_start)
-                       ri = vma->vm_file->private_data;
-               up_read(&current->mm->mmap_sem);
-               if (!ri && cpu_has_feature(CPU_FTR_ARCH_201)) {
-                       pr_err("CPU requires an RMO\n");
-                       return -EINVAL;
+       if (vma->vm_file && vma->vm_file->f_op == &kvm_rma_fops &&
+           hva == vma->vm_start)
+               ri = vma->vm_file->private_data;
+
+       up_read(&current->mm->mmap_sem);
+
+       if (!ri) {
+               /* On POWER7, use VRMA; on PPC970, give up */
+               err = -EPERM;
+               if (cpu_has_feature(CPU_FTR_ARCH_201)) {
+                       pr_err("KVM: CPU requires an RMO\n");
+                       goto out;
                }
-       }
 
-       if (ri) {
-               unsigned long rma_size;
-               unsigned long lpcr;
-               long rmls;
+               /* We can handle 4k, 64k or 16M pages in the VRMA */
+               err = -EINVAL;
+               if (!(psize == 0x1000 || psize == 0x10000 ||
+                     psize == 0x1000000))
+                       goto out;
+
+               /* Update VRMASD field in the LPCR */
+               senc = slb_pgsize_encoding(psize);
+               kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
+                       (VRMA_VSID << SLB_VSID_SHIFT_1T);
+               lpcr = kvm->arch.lpcr & ~LPCR_VRMASD;
+               lpcr |= senc << (LPCR_VRMASD_SH - 4);
+               kvm->arch.lpcr = lpcr;
 
-               rma_size = ri->npages << PAGE_SHIFT;
-               if (rma_size > mem->memory_size)
-                       rma_size = mem->memory_size;
+               /* Create HPTEs in the hash page table for the VRMA */
+               kvmppc_map_vrma(vcpu, memslot, porder);
+
+       } else {
+               /* Set up to use an RMO region */
+               rma_size = ri->npages;
+               if (rma_size > memslot->npages)
+                       rma_size = memslot->npages;
+               rma_size <<= PAGE_SHIFT;
                rmls = lpcr_rmls(rma_size);
+               err = -EINVAL;
                if (rmls < 0) {
-                       pr_err("Can't use RMA of 0x%lx bytes\n", rma_size);
-                       return -EINVAL;
+                       pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
+                       goto out;
                }
                atomic_inc(&ri->use_count);
                kvm->arch.rma = ri;
-               kvm->arch.n_rma_pages = rma_size >> porder;
 
                /* Update LPCR and RMOR */
                lpcr = kvm->arch.lpcr;
@@ -1155,53 +1310,35 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm,
                        kvm->arch.rmor = kvm->arch.rma->base_pfn << PAGE_SHIFT;
                }
                kvm->arch.lpcr = lpcr;
-               pr_info("Using RMO at %lx size %lx (LPCR = %lx)\n",
+               pr_info("KVM: Using RMO at %lx size %lx (LPCR = %lx)\n",
                        ri->base_pfn << PAGE_SHIFT, rma_size, lpcr);
-       }
 
-       pg_ix = mem->guest_phys_addr >> porder;
-       pginfo = kvm->arch.ram_pginfo + pg_ix;
-       for (i = 0; i < npages; ++i, ++pg_ix) {
-               if (ri && pg_ix < kvm->arch.n_rma_pages) {
-                       pginfo[i].pfn = ri->base_pfn +
-                               (pg_ix << (porder - PAGE_SHIFT));
-                       continue;
-               }
-               hva = mem->userspace_addr + (i << porder);
-               page = hva_to_page(hva);
-               if (!page) {
-                       pr_err("oops, no pfn for hva %lx\n", hva);
-                       goto err;
-               }
-               /* Check it's a 16MB page */
-               if (!PageHead(page) ||
-                   compound_order(page) != (LARGE_PAGE_ORDER - PAGE_SHIFT)) {
-                       pr_err("page at %lx isn't 16MB (o=%d)\n",
-                              hva, compound_order(page));
-                       goto err;
-               }
-               pginfo[i].pfn = page_to_pfn(page);
+               /* Initialize phys addrs of pages in RMO */
+               npages = ri->npages;
+               porder = __ilog2(npages);
+               physp = kvm->arch.slot_phys[memslot->id];
+               spin_lock(&kvm->arch.slot_phys_lock);
+               for (i = 0; i < npages; ++i)
+                       physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) + porder;
+               spin_unlock(&kvm->arch.slot_phys_lock);
        }
 
-       return 0;
-
- err:
-       return -EINVAL;
-}
+       /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
+       smp_wmb();
+       kvm->arch.rma_setup_done = 1;
+       err = 0;
+ out:
+       mutex_unlock(&kvm->lock);
+       return err;
 
-void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
-{
-       if (mem->guest_phys_addr == 0 && mem->memory_size != 0 &&
-           !kvm->arch.rma)
-               kvmppc_map_vrma(kvm, mem);
+ up_out:
+       up_read(&current->mm->mmap_sem);
+       goto out;
 }
 
 int kvmppc_core_init_vm(struct kvm *kvm)
 {
        long r;
-       unsigned long npages = 1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER);
-       long err = -ENOMEM;
        unsigned long lpcr;
 
        /* Allocate hashed page table */
@@ -1211,19 +1348,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 
        INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
 
-       kvm->arch.ram_pginfo = kzalloc(npages * sizeof(struct kvmppc_pginfo),
-                                      GFP_KERNEL);
-       if (!kvm->arch.ram_pginfo) {
-               pr_err("kvmppc_core_init_vm: couldn't alloc %lu bytes\n",
-                      npages * sizeof(struct kvmppc_pginfo));
-               goto out_free;
-       }
-
-       kvm->arch.ram_npages = 0;
-       kvm->arch.ram_psize = 1ul << LARGE_PAGE_ORDER;
-       kvm->arch.ram_porder = LARGE_PAGE_ORDER;
        kvm->arch.rma = NULL;
-       kvm->arch.n_rma_pages = 0;
 
        kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
 
@@ -1241,30 +1366,25 @@ int kvmppc_core_init_vm(struct kvm *kvm)
                kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR);
                lpcr &= LPCR_PECE | LPCR_LPES;
                lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE |
-                       LPCR_VPM0 | LPCR_VRMA_L;
+                       LPCR_VPM0 | LPCR_VPM1;
+               kvm->arch.vrma_slb_v = SLB_VSID_B_1T |
+                       (VRMA_VSID << SLB_VSID_SHIFT_1T);
        }
        kvm->arch.lpcr = lpcr;
 
+       kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206);
+       spin_lock_init(&kvm->arch.slot_phys_lock);
        return 0;
-
- out_free:
-       kvmppc_free_hpt(kvm);
-       return err;
 }
 
 void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
-       struct kvmppc_pginfo *pginfo;
        unsigned long i;
 
-       if (kvm->arch.ram_pginfo) {
-               pginfo = kvm->arch.ram_pginfo;
-               kvm->arch.ram_pginfo = NULL;
-               for (i = kvm->arch.n_rma_pages; i < kvm->arch.ram_npages; ++i)
-                       if (pginfo[i].pfn)
-                               put_page(pfn_to_page(pginfo[i].pfn));
-               kfree(pginfo);
-       }
+       if (!kvm->arch.using_mmu_notifiers)
+               for (i = 0; i < KVM_MEM_SLOTS_NUM; i++)
+                       unpin_slot(kvm, i);
+
        if (kvm->arch.rma) {
                kvm_release_rma(kvm->arch.rma);
                kvm->arch.rma = NULL;
index a795a13f4a70f9ddc212e8d125857ad50232248a..bed1279aa6a8788a8308b8966ef4c970f8aafd36 100644 (file)
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 
+#define KVM_LINEAR_RMA         0
+#define KVM_LINEAR_HPT         1
+
+static void __init kvm_linear_init_one(ulong size, int count, int type);
+static struct kvmppc_linear_info *kvm_alloc_linear(int type);
+static void kvm_release_linear(struct kvmppc_linear_info *ri);
+
+/*************** RMA *************/
+
 /*
  * This maintains a list of RMAs (real mode areas) for KVM guests to use.
  * Each RMA has to be physically contiguous and of a size that the
 static unsigned long kvm_rma_size = 64 << 20;  /* 64MB */
 static unsigned long kvm_rma_count;
 
-static int __init early_parse_rma_size(char *p)
-{
-       if (!p)
-               return 1;
-
-       kvm_rma_size = memparse(p, &p);
-
-       return 0;
-}
-early_param("kvm_rma_size", early_parse_rma_size);
-
-static int __init early_parse_rma_count(char *p)
-{
-       if (!p)
-               return 1;
-
-       kvm_rma_count = simple_strtoul(p, NULL, 0);
-
-       return 0;
-}
-early_param("kvm_rma_count", early_parse_rma_count);
-
-static struct kvmppc_rma_info *rma_info;
-static LIST_HEAD(free_rmas);
-static DEFINE_SPINLOCK(rma_lock);
-
 /* Work out RMLS (real mode limit selector) field value for a given RMA size.
    Assumes POWER7 or PPC970. */
 static inline int lpcr_rmls(unsigned long rma_size)
@@ -81,45 +64,106 @@ static inline int lpcr_rmls(unsigned long rma_size)
        }
 }
 
+static int __init early_parse_rma_size(char *p)
+{
+       if (!p)
+               return 1;
+
+       kvm_rma_size = memparse(p, &p);
+
+       return 0;
+}
+early_param("kvm_rma_size", early_parse_rma_size);
+
+static int __init early_parse_rma_count(char *p)
+{
+       if (!p)
+               return 1;
+
+       kvm_rma_count = simple_strtoul(p, NULL, 0);
+
+       return 0;
+}
+early_param("kvm_rma_count", early_parse_rma_count);
+
+struct kvmppc_linear_info *kvm_alloc_rma(void)
+{
+       return kvm_alloc_linear(KVM_LINEAR_RMA);
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_rma);
+
+void kvm_release_rma(struct kvmppc_linear_info *ri)
+{
+       kvm_release_linear(ri);
+}
+EXPORT_SYMBOL_GPL(kvm_release_rma);
+
+/*************** HPT *************/
+
 /*
- * Called at boot time while the bootmem allocator is active,
- * to allocate contiguous physical memory for the real memory
- * areas for guests.
+ * This maintains a list of big linear HPT tables that contain the GVA->HPA
+ * memory mappings. If we don't reserve those early on, we might not be able
+ * to get a big (usually 16MB) linear memory region from the kernel anymore.
  */
-void __init kvm_rma_init(void)
+
+static unsigned long kvm_hpt_count;
+
+static int __init early_parse_hpt_count(char *p)
+{
+       if (!p)
+               return 1;
+
+       kvm_hpt_count = simple_strtoul(p, NULL, 0);
+
+       return 0;
+}
+early_param("kvm_hpt_count", early_parse_hpt_count);
+
+struct kvmppc_linear_info *kvm_alloc_hpt(void)
+{
+       return kvm_alloc_linear(KVM_LINEAR_HPT);
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
+
+void kvm_release_hpt(struct kvmppc_linear_info *li)
+{
+       kvm_release_linear(li);
+}
+EXPORT_SYMBOL_GPL(kvm_release_hpt);
+
+/*************** generic *************/
+
+static LIST_HEAD(free_linears);
+static DEFINE_SPINLOCK(linear_lock);
+
+static void __init kvm_linear_init_one(ulong size, int count, int type)
 {
        unsigned long i;
        unsigned long j, npages;
-       void *rma;
+       void *linear;
        struct page *pg;
+       const char *typestr;
+       struct kvmppc_linear_info *linear_info;
 
-       /* Only do this on PPC970 in HV mode */
-       if (!cpu_has_feature(CPU_FTR_HVMODE) ||
-           !cpu_has_feature(CPU_FTR_ARCH_201))
-               return;
-
-       if (!kvm_rma_size || !kvm_rma_count)
+       if (!count)
                return;
 
-       /* Check that the requested size is one supported in hardware */
-       if (lpcr_rmls(kvm_rma_size) < 0) {
-               pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
-               return;
-       }
-
-       npages = kvm_rma_size >> PAGE_SHIFT;
-       rma_info = alloc_bootmem(kvm_rma_count * sizeof(struct kvmppc_rma_info));
-       for (i = 0; i < kvm_rma_count; ++i) {
-               rma = alloc_bootmem_align(kvm_rma_size, kvm_rma_size);
-               pr_info("Allocated KVM RMA at %p (%ld MB)\n", rma,
-                       kvm_rma_size >> 20);
-               rma_info[i].base_virt = rma;
-               rma_info[i].base_pfn = __pa(rma) >> PAGE_SHIFT;
-               rma_info[i].npages = npages;
-               list_add_tail(&rma_info[i].list, &free_rmas);
-               atomic_set(&rma_info[i].use_count, 0);
-
-               pg = pfn_to_page(rma_info[i].base_pfn);
+       typestr = (type == KVM_LINEAR_RMA) ? "RMA" : "HPT";
+
+       npages = size >> PAGE_SHIFT;
+       linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
+       for (i = 0; i < count; ++i) {
+               linear = alloc_bootmem_align(size, size);
+               pr_info("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
+                       size >> 20);
+               linear_info[i].base_virt = linear;
+               linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
+               linear_info[i].npages = npages;
+               linear_info[i].type = type;
+               list_add_tail(&linear_info[i].list, &free_linears);
+               atomic_set(&linear_info[i].use_count, 0);
+
+               pg = pfn_to_page(linear_info[i].base_pfn);
                for (j = 0; j < npages; ++j) {
                        atomic_inc(&pg->_count);
                        ++pg;
@@ -127,30 +171,59 @@ void __init kvm_rma_init(void)
        }
 }
 
-struct kvmppc_rma_info *kvm_alloc_rma(void)
+static struct kvmppc_linear_info *kvm_alloc_linear(int type)
 {
-       struct kvmppc_rma_info *ri;
+       struct kvmppc_linear_info *ri;
 
        ri = NULL;
-       spin_lock(&rma_lock);
-       if (!list_empty(&free_rmas)) {
-               ri = list_first_entry(&free_rmas, struct kvmppc_rma_info, list);
+       spin_lock(&linear_lock);
+       list_for_each_entry(ri, &free_linears, list) {
+               if (ri->type != type)
+                       continue;
+
                list_del(&ri->list);
                atomic_inc(&ri->use_count);
+               break;
        }
-       spin_unlock(&rma_lock);
+       spin_unlock(&linear_lock);
+       memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
        return ri;
 }
-EXPORT_SYMBOL_GPL(kvm_alloc_rma);
 
-void kvm_release_rma(struct kvmppc_rma_info *ri)
+static void kvm_release_linear(struct kvmppc_linear_info *ri)
 {
        if (atomic_dec_and_test(&ri->use_count)) {
-               spin_lock(&rma_lock);
-               list_add_tail(&ri->list, &free_rmas);
-               spin_unlock(&rma_lock);
+               spin_lock(&linear_lock);
+               list_add_tail(&ri->list, &free_linears);
+               spin_unlock(&linear_lock);
 
        }
 }
-EXPORT_SYMBOL_GPL(kvm_release_rma);
 
+/*
+ * Called at boot time while the bootmem allocator is active,
+ * to allocate contiguous physical memory for the hash page
+ * tables for guests.
+ */
+void __init kvm_linear_init(void)
+{
+       /* HPT */
+       kvm_linear_init_one(1 << HPT_ORDER, kvm_hpt_count, KVM_LINEAR_HPT);
+
+       /* RMA */
+       /* Only do this on PPC970 in HV mode */
+       if (!cpu_has_feature(CPU_FTR_HVMODE) ||
+           !cpu_has_feature(CPU_FTR_ARCH_201))
+               return;
+
+       if (!kvm_rma_size || !kvm_rma_count)
+               return;
+
+       /* Check that the requested size is one supported in hardware */
+       if (lpcr_rmls(kvm_rma_size) < 0) {
+               pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
+               return;
+       }
+
+       kvm_linear_init_one(kvm_rma_size, kvm_rma_count, KVM_LINEAR_RMA);
+}
index bacb0cfa3602023ec28755766899d5433a20bf5c..def880aea63a34eb0d49dceda27e27c848dffc35 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/hugetlb.h>
+#include <linux/module.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
 
-/* For now use fixed-size 16MB page table */
-#define HPT_ORDER      24
-#define HPT_NPTEG      (1ul << (HPT_ORDER - 7))        /* 128B per pteg */
-#define HPT_HASH_MASK  (HPT_NPTEG - 1)
+/* Translate address of a vmalloc'd thing to a linear map address */
+static void *real_vmalloc_addr(void *x)
+{
+       unsigned long addr = (unsigned long) x;
+       pte_t *p;
 
-#define HPTE_V_HVLOCK  0x40UL
+       p = find_linux_pte(swapper_pg_dir, addr);
+       if (!p || !pte_present(*p))
+               return NULL;
+       /* assume we don't have huge pages in vmalloc space... */
+       addr = (pte_pfn(*p) << PAGE_SHIFT) | (addr & ~PAGE_MASK);
+       return __va(addr);
+}
 
-static inline long lock_hpte(unsigned long *hpte, unsigned long bits)
+/*
+ * Add this HPTE into the chain for the real page.
+ * Must be called with the chain locked; it unlocks the chain.
+ */
+void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
+                            unsigned long *rmap, long pte_index, int realmode)
 {
-       unsigned long tmp, old;
+       struct revmap_entry *head, *tail;
+       unsigned long i;
 
-       asm volatile("  ldarx   %0,0,%2\n"
-                    "  and.    %1,%0,%3\n"
-                    "  bne     2f\n"
-                    "  ori     %0,%0,%4\n"
-                    "  stdcx.  %0,0,%2\n"
-                    "  beq+    2f\n"
-                    "  li      %1,%3\n"
-                    "2:        isync"
-                    : "=&r" (tmp), "=&r" (old)
-                    : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
-                    : "cc", "memory");
-       return old == 0;
+       if (*rmap & KVMPPC_RMAP_PRESENT) {
+               i = *rmap & KVMPPC_RMAP_INDEX;
+               head = &kvm->arch.revmap[i];
+               if (realmode)
+                       head = real_vmalloc_addr(head);
+               tail = &kvm->arch.revmap[head->back];
+               if (realmode)
+                       tail = real_vmalloc_addr(tail);
+               rev->forw = i;
+               rev->back = head->back;
+               tail->forw = pte_index;
+               head->back = pte_index;
+       } else {
+               rev->forw = rev->back = pte_index;
+               i = pte_index;
+       }
+       smp_wmb();
+       *rmap = i | KVMPPC_RMAP_REFERENCED | KVMPPC_RMAP_PRESENT; /* unlock */
+}
+EXPORT_SYMBOL_GPL(kvmppc_add_revmap_chain);
+
+/* Remove this HPTE from the chain for a real page */
+static void remove_revmap_chain(struct kvm *kvm, long pte_index,
+                               struct revmap_entry *rev,
+                               unsigned long hpte_v, unsigned long hpte_r)
+{
+       struct revmap_entry *next, *prev;
+       unsigned long gfn, ptel, head;
+       struct kvm_memory_slot *memslot;
+       unsigned long *rmap;
+       unsigned long rcbits;
+
+       rcbits = hpte_r & (HPTE_R_R | HPTE_R_C);
+       ptel = rev->guest_rpte |= rcbits;
+       gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
+       memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+               return;
+
+       rmap = real_vmalloc_addr(&memslot->rmap[gfn - memslot->base_gfn]);
+       lock_rmap(rmap);
+
+       head = *rmap & KVMPPC_RMAP_INDEX;
+       next = real_vmalloc_addr(&kvm->arch.revmap[rev->forw]);
+       prev = real_vmalloc_addr(&kvm->arch.revmap[rev->back]);
+       next->back = rev->back;
+       prev->forw = rev->forw;
+       if (head == pte_index) {
+               head = rev->forw;
+               if (head == pte_index)
+                       *rmap &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX);
+               else
+                       *rmap = (*rmap & ~KVMPPC_RMAP_INDEX) | head;
+       }
+       *rmap |= rcbits << KVMPPC_RMAP_RC_SHIFT;
+       unlock_rmap(rmap);
+}
+
+static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
+                             int writing, unsigned long *pte_sizep)
+{
+       pte_t *ptep;
+       unsigned long ps = *pte_sizep;
+       unsigned int shift;
+
+       ptep = find_linux_pte_or_hugepte(vcpu->arch.pgdir, hva, &shift);
+       if (!ptep)
+               return __pte(0);
+       if (shift)
+               *pte_sizep = 1ul << shift;
+       else
+               *pte_sizep = PAGE_SIZE;
+       if (ps > *pte_sizep)
+               return __pte(0);
+       if (!pte_present(*ptep))
+               return __pte(0);
+       return kvmppc_read_update_linux_pte(ptep, writing);
+}
+
+static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
+{
+       asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
+       hpte[0] = hpte_v;
 }
 
 long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
                    long pte_index, unsigned long pteh, unsigned long ptel)
 {
-       unsigned long porder;
        struct kvm *kvm = vcpu->kvm;
-       unsigned long i, lpn, pa;
+       unsigned long i, pa, gpa, gfn, psize;
+       unsigned long slot_fn, hva;
        unsigned long *hpte;
+       struct revmap_entry *rev;
+       unsigned long g_ptel = ptel;
+       struct kvm_memory_slot *memslot;
+       unsigned long *physp, pte_size;
+       unsigned long is_io;
+       unsigned long *rmap;
+       pte_t pte;
+       unsigned int writing;
+       unsigned long mmu_seq;
+       unsigned long rcbits;
+       bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
 
-       /* only handle 4k, 64k and 16M pages for now */
-       porder = 12;
-       if (pteh & HPTE_V_LARGE) {
-               if (cpu_has_feature(CPU_FTR_ARCH_206) &&
-                   (ptel & 0xf000) == 0x1000) {
-                       /* 64k page */
-                       porder = 16;
-               } else if ((ptel & 0xff000) == 0) {
-                       /* 16M page */
-                       porder = 24;
-                       /* lowest AVA bit must be 0 for 16M pages */
-                       if (pteh & 0x80)
-                               return H_PARAMETER;
-               } else
+       psize = hpte_page_size(pteh, ptel);
+       if (!psize)
+               return H_PARAMETER;
+       writing = hpte_is_writable(ptel);
+       pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
+
+       /* used later to detect if we might have been invalidated */
+       mmu_seq = kvm->mmu_notifier_seq;
+       smp_rmb();
+
+       /* Find the memslot (if any) for this address */
+       gpa = (ptel & HPTE_R_RPN) & ~(psize - 1);
+       gfn = gpa >> PAGE_SHIFT;
+       memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
+       pa = 0;
+       is_io = ~0ul;
+       rmap = NULL;
+       if (!(memslot && !(memslot->flags & KVM_MEMSLOT_INVALID))) {
+               /* PPC970 can't do emulated MMIO */
+               if (!cpu_has_feature(CPU_FTR_ARCH_206))
                        return H_PARAMETER;
+               /* Emulated MMIO - mark this with key=31 */
+               pteh |= HPTE_V_ABSENT;
+               ptel |= HPTE_R_KEY_HI | HPTE_R_KEY_LO;
+               goto do_insert;
        }
-       lpn = (ptel & HPTE_R_RPN) >> kvm->arch.ram_porder;
-       if (lpn >= kvm->arch.ram_npages || porder > kvm->arch.ram_porder)
-               return H_PARAMETER;
-       pa = kvm->arch.ram_pginfo[lpn].pfn << PAGE_SHIFT;
-       if (!pa)
+
+       /* Check if the requested page fits entirely in the memslot. */
+       if (!slot_is_aligned(memslot, psize))
                return H_PARAMETER;
-       /* Check WIMG */
-       if ((ptel & HPTE_R_WIMG) != HPTE_R_M &&
-           (ptel & HPTE_R_WIMG) != (HPTE_R_W | HPTE_R_I | HPTE_R_M))
+       slot_fn = gfn - memslot->base_gfn;
+       rmap = &memslot->rmap[slot_fn];
+
+       if (!kvm->arch.using_mmu_notifiers) {
+               physp = kvm->arch.slot_phys[memslot->id];
+               if (!physp)
+                       return H_PARAMETER;
+               physp += slot_fn;
+               if (realmode)
+                       physp = real_vmalloc_addr(physp);
+               pa = *physp;
+               if (!pa)
+                       return H_TOO_HARD;
+               is_io = pa & (HPTE_R_I | HPTE_R_W);
+               pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
+               pa &= PAGE_MASK;
+       } else {
+               /* Translate to host virtual address */
+               hva = gfn_to_hva_memslot(memslot, gfn);
+
+               /* Look up the Linux PTE for the backing page */
+               pte_size = psize;
+               pte = lookup_linux_pte(vcpu, hva, writing, &pte_size);
+               if (pte_present(pte)) {
+                       if (writing && !pte_write(pte))
+                               /* make the actual HPTE be read-only */
+                               ptel = hpte_make_readonly(ptel);
+                       is_io = hpte_cache_bits(pte_val(pte));
+                       pa = pte_pfn(pte) << PAGE_SHIFT;
+               }
+       }
+       if (pte_size < psize)
                return H_PARAMETER;
-       pteh &= ~0x60UL;
-       ptel &= ~(HPTE_R_PP0 - kvm->arch.ram_psize);
+       if (pa && pte_size > psize)
+               pa |= gpa & (pte_size - 1);
+
+       ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
-       if (pte_index >= (HPT_NPTEG << 3))
+
+       if (pa)
+               pteh |= HPTE_V_VALID;
+       else
+               pteh |= HPTE_V_ABSENT;
+
+       /* Check WIMG */
+       if (is_io != ~0ul && !hpte_cache_flags_ok(ptel, is_io)) {
+               if (is_io)
+                       return H_PARAMETER;
+               /*
+                * Allow guest to map emulated device memory as
+                * uncacheable, but actually make it cacheable.
+                */
+               ptel &= ~(HPTE_R_W|HPTE_R_I|HPTE_R_G);
+               ptel |= HPTE_R_M;
+       }
+
+       /* Find and lock the HPTEG slot to use */
+ do_insert:
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
        if (likely((flags & H_EXACT) == 0)) {
                pte_index &= ~7UL;
                hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-               for (i = 0; ; ++i) {
-                       if (i == 8)
-                               return H_PTEG_FULL;
+               for (i = 0; i < 8; ++i) {
                        if ((*hpte & HPTE_V_VALID) == 0 &&
-                           lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
+                           try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
+                                         HPTE_V_ABSENT))
                                break;
                        hpte += 2;
                }
+               if (i == 8) {
+                       /*
+                        * Since try_lock_hpte doesn't retry (not even stdcx.
+                        * failures), it could be that there is a free slot
+                        * but we transiently failed to lock it.  Try again,
+                        * actually locking each slot and checking it.
+                        */
+                       hpte -= 16;
+                       for (i = 0; i < 8; ++i) {
+                               while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+                                       cpu_relax();
+                               if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)))
+                                       break;
+                               *hpte &= ~HPTE_V_HVLOCK;
+                               hpte += 2;
+                       }
+                       if (i == 8)
+                               return H_PTEG_FULL;
+               }
+               pte_index += i;
        } else {
-               i = 0;
                hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-               if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
-                       return H_PTEG_FULL;
+               if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
+                                  HPTE_V_ABSENT)) {
+                       /* Lock the slot and check again */
+                       while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+                               cpu_relax();
+                       if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+                               *hpte &= ~HPTE_V_HVLOCK;
+                               return H_PTEG_FULL;
+                       }
+               }
        }
+
+       /* Save away the guest's idea of the second HPTE dword */
+       rev = &kvm->arch.revmap[pte_index];
+       if (realmode)
+               rev = real_vmalloc_addr(rev);
+       if (rev)
+               rev->guest_rpte = g_ptel;
+
+       /* Link HPTE into reverse-map chain */
+       if (pteh & HPTE_V_VALID) {
+               if (realmode)
+                       rmap = real_vmalloc_addr(rmap);
+               lock_rmap(rmap);
+               /* Check for pending invalidations under the rmap chain lock */
+               if (kvm->arch.using_mmu_notifiers &&
+                   mmu_notifier_retry(vcpu, mmu_seq)) {
+                       /* inval in progress, write a non-present HPTE */
+                       pteh |= HPTE_V_ABSENT;
+                       pteh &= ~HPTE_V_VALID;
+                       unlock_rmap(rmap);
+               } else {
+                       kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index,
+                                               realmode);
+                       /* Only set R/C in real HPTE if already set in *rmap */
+                       rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
+                       ptel &= rcbits | ~(HPTE_R_R | HPTE_R_C);
+               }
+       }
+
        hpte[1] = ptel;
+
+       /* Write the first HPTE dword, unlocking the HPTE and making it valid */
        eieio();
        hpte[0] = pteh;
        asm volatile("ptesync" : : : "memory");
-       atomic_inc(&kvm->arch.ram_pginfo[lpn].refcnt);
-       vcpu->arch.gpr[4] = pte_index + i;
+
+       vcpu->arch.gpr[4] = pte_index;
        return H_SUCCESS;
 }
+EXPORT_SYMBOL_GPL(kvmppc_h_enter);
 
 #define LOCK_TOKEN     (*(u32 *)(&get_paca()->lock_token))
 
@@ -137,37 +350,46 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
        struct kvm *kvm = vcpu->kvm;
        unsigned long *hpte;
        unsigned long v, r, rb;
+       struct revmap_entry *rev;
 
-       if (pte_index >= (HPT_NPTEG << 3))
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
        hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-       while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+       while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
                cpu_relax();
-       if ((hpte[0] & HPTE_V_VALID) == 0 ||
+       if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
            ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
            ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
                hpte[0] &= ~HPTE_V_HVLOCK;
                return H_NOT_FOUND;
        }
-       if (atomic_read(&kvm->online_vcpus) == 1)
-               flags |= H_LOCAL;
-       vcpu->arch.gpr[4] = v = hpte[0] & ~HPTE_V_HVLOCK;
-       vcpu->arch.gpr[5] = r = hpte[1];
-       rb = compute_tlbie_rb(v, r, pte_index);
-       hpte[0] = 0;
-       if (!(flags & H_LOCAL)) {
-               while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
-                       cpu_relax();
-               asm volatile("ptesync" : : : "memory");
-               asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
-                            : : "r" (rb), "r" (kvm->arch.lpid));
-               asm volatile("ptesync" : : : "memory");
-               kvm->arch.tlbie_lock = 0;
-       } else {
-               asm volatile("ptesync" : : : "memory");
-               asm volatile("tlbiel %0" : : "r" (rb));
-               asm volatile("ptesync" : : : "memory");
+
+       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+       v = hpte[0] & ~HPTE_V_HVLOCK;
+       if (v & HPTE_V_VALID) {
+               hpte[0] &= ~HPTE_V_VALID;
+               rb = compute_tlbie_rb(v, hpte[1], pte_index);
+               if (!(flags & H_LOCAL) && atomic_read(&kvm->online_vcpus) > 1) {
+                       while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+                               cpu_relax();
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                                    : : "r" (rb), "r" (kvm->arch.lpid));
+                       asm volatile("ptesync" : : : "memory");
+                       kvm->arch.tlbie_lock = 0;
+               } else {
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile("tlbiel %0" : : "r" (rb));
+                       asm volatile("ptesync" : : : "memory");
+               }
+               /* Read PTE low word after tlbie to get final R/C values */
+               remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
        }
+       r = rev->guest_rpte;
+       unlock_hpte(hpte, 0);
+
+       vcpu->arch.gpr[4] = v;
+       vcpu->arch.gpr[5] = r;
        return H_SUCCESS;
 }
 
@@ -175,78 +397,117 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = vcpu->kvm;
        unsigned long *args = &vcpu->arch.gpr[4];
-       unsigned long *hp, tlbrb[4];
-       long int i, found;
-       long int n_inval = 0;
-       unsigned long flags, req, pte_index;
+       unsigned long *hp, *hptes[4], tlbrb[4];
+       long int i, j, k, n, found, indexes[4];
+       unsigned long flags, req, pte_index, rcbits;
        long int local = 0;
        long int ret = H_SUCCESS;
+       struct revmap_entry *rev, *revs[4];
 
        if (atomic_read(&kvm->online_vcpus) == 1)
                local = 1;
-       for (i = 0; i < 4; ++i) {
-               pte_index = args[i * 2];
-               flags = pte_index >> 56;
-               pte_index &= ((1ul << 56) - 1);
-               req = flags >> 6;
-               flags &= 3;
-               if (req == 3)
-                       break;
-               if (req != 1 || flags == 3 ||
-                   pte_index >= (HPT_NPTEG << 3)) {
-                       /* parameter error */
-                       args[i * 2] = ((0xa0 | flags) << 56) + pte_index;
-                       ret = H_PARAMETER;
-                       break;
-               }
-               hp = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-               while (!lock_hpte(hp, HPTE_V_HVLOCK))
-                       cpu_relax();
-               found = 0;
-               if (hp[0] & HPTE_V_VALID) {
-                       switch (flags & 3) {
-                       case 0:         /* absolute */
-                               found = 1;
+       for (i = 0; i < 4 && ret == H_SUCCESS; ) {
+               n = 0;
+               for (; i < 4; ++i) {
+                       j = i * 2;
+                       pte_index = args[j];
+                       flags = pte_index >> 56;
+                       pte_index &= ((1ul << 56) - 1);
+                       req = flags >> 6;
+                       flags &= 3;
+                       if (req == 3) {         /* no more requests */
+                               i = 4;
                                break;
-                       case 1:         /* andcond */
-                               if (!(hp[0] & args[i * 2 + 1]))
-                                       found = 1;
+                       }
+                       if (req != 1 || flags == 3 || pte_index >= HPT_NPTE) {
+                               /* parameter error */
+                               args[j] = ((0xa0 | flags) << 56) + pte_index;
+                               ret = H_PARAMETER;
                                break;
-                       case 2:         /* AVPN */
-                               if ((hp[0] & ~0x7fUL) == args[i * 2 + 1])
+                       }
+                       hp = (unsigned long *)
+                               (kvm->arch.hpt_virt + (pte_index << 4));
+                       /* to avoid deadlock, don't spin except for first */
+                       if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) {
+                               if (n)
+                                       break;
+                               while (!try_lock_hpte(hp, HPTE_V_HVLOCK))
+                                       cpu_relax();
+                       }
+                       found = 0;
+                       if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) {
+                               switch (flags & 3) {
+                               case 0:         /* absolute */
                                        found = 1;
-                               break;
+                                       break;
+                               case 1:         /* andcond */
+                                       if (!(hp[0] & args[j + 1]))
+                                               found = 1;
+                                       break;
+                               case 2:         /* AVPN */
+                                       if ((hp[0] & ~0x7fUL) == args[j + 1])
+                                               found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found) {
+                               hp[0] &= ~HPTE_V_HVLOCK;
+                               args[j] = ((0x90 | flags) << 56) + pte_index;
+                               continue;
                        }
+
+                       args[j] = ((0x80 | flags) << 56) + pte_index;
+                       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+
+                       if (!(hp[0] & HPTE_V_VALID)) {
+                               /* insert R and C bits from PTE */
+                               rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
+                               args[j] |= rcbits << (56 - 5);
+                               continue;
+                       }
+
+                       hp[0] &= ~HPTE_V_VALID;         /* leave it locked */
+                       tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+                       indexes[n] = j;
+                       hptes[n] = hp;
+                       revs[n] = rev;
+                       ++n;
+               }
+
+               if (!n)
+                       break;
+
+               /* Now that we've collected a batch, do the tlbies */
+               if (!local) {
+                       while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+                               cpu_relax();
+                       asm volatile("ptesync" : : : "memory");
+                       for (k = 0; k < n; ++k)
+                               asm volatile(PPC_TLBIE(%1,%0) : :
+                                            "r" (tlbrb[k]),
+                                            "r" (kvm->arch.lpid));
+                       asm volatile("eieio; tlbsync; ptesync" : : : "memory");
+                       kvm->arch.tlbie_lock = 0;
+               } else {
+                       asm volatile("ptesync" : : : "memory");
+                       for (k = 0; k < n; ++k)
+                               asm volatile("tlbiel %0" : : "r" (tlbrb[k]));
+                       asm volatile("ptesync" : : : "memory");
                }
-               if (!found) {
-                       hp[0] &= ~HPTE_V_HVLOCK;
-                       args[i * 2] = ((0x90 | flags) << 56) + pte_index;
-                       continue;
+
+               /* Read PTE low words after tlbie to get final R/C values */
+               for (k = 0; k < n; ++k) {
+                       j = indexes[k];
+                       pte_index = args[j] & ((1ul << 56) - 1);
+                       hp = hptes[k];
+                       rev = revs[k];
+                       remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
+                       rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
+                       args[j] |= rcbits << (56 - 5);
+                       hp[0] = 0;
                }
-               /* insert R and C bits from PTE */
-               flags |= (hp[1] >> 5) & 0x0c;
-               args[i * 2] = ((0x80 | flags) << 56) + pte_index;
-               tlbrb[n_inval++] = compute_tlbie_rb(hp[0], hp[1], pte_index);
-               hp[0] = 0;
-       }
-       if (n_inval == 0)
-               return ret;
-
-       if (!local) {
-               while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
-                       cpu_relax();
-               asm volatile("ptesync" : : : "memory");
-               for (i = 0; i < n_inval; ++i)
-                       asm volatile(PPC_TLBIE(%1,%0)
-                                    : : "r" (tlbrb[i]), "r" (kvm->arch.lpid));
-               asm volatile("eieio; tlbsync; ptesync" : : : "memory");
-               kvm->arch.tlbie_lock = 0;
-       } else {
-               asm volatile("ptesync" : : : "memory");
-               for (i = 0; i < n_inval; ++i)
-                       asm volatile("tlbiel %0" : : "r" (tlbrb[i]));
-               asm volatile("ptesync" : : : "memory");
        }
+
        return ret;
 }
 
@@ -256,40 +517,55 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 {
        struct kvm *kvm = vcpu->kvm;
        unsigned long *hpte;
-       unsigned long v, r, rb;
+       struct revmap_entry *rev;
+       unsigned long v, r, rb, mask, bits;
 
-       if (pte_index >= (HPT_NPTEG << 3))
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
+
        hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-       while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+       while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
                cpu_relax();
-       if ((hpte[0] & HPTE_V_VALID) == 0 ||
+       if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
            ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
                hpte[0] &= ~HPTE_V_HVLOCK;
                return H_NOT_FOUND;
        }
+
        if (atomic_read(&kvm->online_vcpus) == 1)
                flags |= H_LOCAL;
        v = hpte[0];
-       r = hpte[1] & ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
-                       HPTE_R_KEY_HI | HPTE_R_KEY_LO);
-       r |= (flags << 55) & HPTE_R_PP0;
-       r |= (flags << 48) & HPTE_R_KEY_HI;
-       r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
-       rb = compute_tlbie_rb(v, r, pte_index);
-       hpte[0] = v & ~HPTE_V_VALID;
-       if (!(flags & H_LOCAL)) {
-               while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
-                       cpu_relax();
-               asm volatile("ptesync" : : : "memory");
-               asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
-                            : : "r" (rb), "r" (kvm->arch.lpid));
-               asm volatile("ptesync" : : : "memory");
-               kvm->arch.tlbie_lock = 0;
-       } else {
-               asm volatile("ptesync" : : : "memory");
-               asm volatile("tlbiel %0" : : "r" (rb));
-               asm volatile("ptesync" : : : "memory");
+       bits = (flags << 55) & HPTE_R_PP0;
+       bits |= (flags << 48) & HPTE_R_KEY_HI;
+       bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+
+       /* Update guest view of 2nd HPTE dword */
+       mask = HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
+               HPTE_R_KEY_HI | HPTE_R_KEY_LO;
+       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+       if (rev) {
+               r = (rev->guest_rpte & ~mask) | bits;
+               rev->guest_rpte = r;
+       }
+       r = (hpte[1] & ~mask) | bits;
+
+       /* Update HPTE */
+       if (v & HPTE_V_VALID) {
+               rb = compute_tlbie_rb(v, r, pte_index);
+               hpte[0] = v & ~HPTE_V_VALID;
+               if (!(flags & H_LOCAL)) {
+                       while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+                               cpu_relax();
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                                    : : "r" (rb), "r" (kvm->arch.lpid));
+                       asm volatile("ptesync" : : : "memory");
+                       kvm->arch.tlbie_lock = 0;
+               } else {
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile("tlbiel %0" : : "r" (rb));
+                       asm volatile("ptesync" : : : "memory");
+               }
        }
        hpte[1] = r;
        eieio();
@@ -298,40 +574,243 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
        return H_SUCCESS;
 }
 
-static unsigned long reverse_xlate(struct kvm *kvm, unsigned long realaddr)
-{
-       long int i;
-       unsigned long offset, rpn;
-
-       offset = realaddr & (kvm->arch.ram_psize - 1);
-       rpn = (realaddr - offset) >> PAGE_SHIFT;
-       for (i = 0; i < kvm->arch.ram_npages; ++i)
-               if (rpn == kvm->arch.ram_pginfo[i].pfn)
-                       return (i << PAGE_SHIFT) + offset;
-       return HPTE_R_RPN;      /* all 1s in the RPN field */
-}
-
 long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
                   unsigned long pte_index)
 {
        struct kvm *kvm = vcpu->kvm;
-       unsigned long *hpte, r;
+       unsigned long *hpte, v, r;
        int i, n = 1;
+       struct revmap_entry *rev = NULL;
 
-       if (pte_index >= (HPT_NPTEG << 3))
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
        if (flags & H_READ_4) {
                pte_index &= ~3;
                n = 4;
        }
+       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
        for (i = 0; i < n; ++i, ++pte_index) {
                hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+               v = hpte[0] & ~HPTE_V_HVLOCK;
                r = hpte[1];
-               if ((flags & H_R_XLATE) && (hpte[0] & HPTE_V_VALID))
-                       r = reverse_xlate(kvm, r & HPTE_R_RPN) |
-                               (r & ~HPTE_R_RPN);
-               vcpu->arch.gpr[4 + i * 2] = hpte[0];
+               if (v & HPTE_V_ABSENT) {
+                       v &= ~HPTE_V_ABSENT;
+                       v |= HPTE_V_VALID;
+               }
+               if (v & HPTE_V_VALID)
+                       r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
+               vcpu->arch.gpr[4 + i * 2] = v;
                vcpu->arch.gpr[5 + i * 2] = r;
        }
        return H_SUCCESS;
 }
+
+void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+                       unsigned long pte_index)
+{
+       unsigned long rb;
+
+       hptep[0] &= ~HPTE_V_VALID;
+       rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+       while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+               cpu_relax();
+       asm volatile("ptesync" : : : "memory");
+       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                    : : "r" (rb), "r" (kvm->arch.lpid));
+       asm volatile("ptesync" : : : "memory");
+       kvm->arch.tlbie_lock = 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
+
+void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+                          unsigned long pte_index)
+{
+       unsigned long rb;
+       unsigned char rbyte;
+
+       rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+       rbyte = (hptep[1] & ~HPTE_R_R) >> 8;
+       /* modify only the second-last byte, which contains the ref bit */
+       *((char *)hptep + 14) = rbyte;
+       while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+               cpu_relax();
+       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                    : : "r" (rb), "r" (kvm->arch.lpid));
+       asm volatile("ptesync" : : : "memory");
+       kvm->arch.tlbie_lock = 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_clear_ref_hpte);
+
+static int slb_base_page_shift[4] = {
+       24,     /* 16M */
+       16,     /* 64k */
+       34,     /* 16G */
+       20,     /* 1M, unsupported */
+};
+
+long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
+                             unsigned long valid)
+{
+       unsigned int i;
+       unsigned int pshift;
+       unsigned long somask;
+       unsigned long vsid, hash;
+       unsigned long avpn;
+       unsigned long *hpte;
+       unsigned long mask, val;
+       unsigned long v, r;
+
+       /* Get page shift, work out hash and AVPN etc. */
+       mask = SLB_VSID_B | HPTE_V_AVPN | HPTE_V_SECONDARY;
+       val = 0;
+       pshift = 12;
+       if (slb_v & SLB_VSID_L) {
+               mask |= HPTE_V_LARGE;
+               val |= HPTE_V_LARGE;
+               pshift = slb_base_page_shift[(slb_v & SLB_VSID_LP) >> 4];
+       }
+       if (slb_v & SLB_VSID_B_1T) {
+               somask = (1UL << 40) - 1;
+               vsid = (slb_v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T;
+               vsid ^= vsid << 25;
+       } else {
+               somask = (1UL << 28) - 1;
+               vsid = (slb_v & ~SLB_VSID_B) >> SLB_VSID_SHIFT;
+       }
+       hash = (vsid ^ ((eaddr & somask) >> pshift)) & HPT_HASH_MASK;
+       avpn = slb_v & ~(somask >> 16); /* also includes B */
+       avpn |= (eaddr & somask) >> 16;
+
+       if (pshift >= 24)
+               avpn &= ~((1UL << (pshift - 16)) - 1);
+       else
+               avpn &= ~0x7fUL;
+       val |= avpn;
+
+       for (;;) {
+               hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7));
+
+               for (i = 0; i < 16; i += 2) {
+                       /* Read the PTE racily */
+                       v = hpte[i] & ~HPTE_V_HVLOCK;
+
+                       /* Check valid/absent, hash, segment size and AVPN */
+                       if (!(v & valid) || (v & mask) != val)
+                               continue;
+
+                       /* Lock the PTE and read it under the lock */
+                       while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK))
+                               cpu_relax();
+                       v = hpte[i] & ~HPTE_V_HVLOCK;
+                       r = hpte[i+1];
+
+                       /*
+                        * Check the HPTE again, including large page size
+                        * Since we don't currently allow any MPSS (mixed
+                        * page-size segment) page sizes, it is sufficient
+                        * to check against the actual page size.
+                        */
+                       if ((v & valid) && (v & mask) == val &&
+                           hpte_page_size(v, r) == (1ul << pshift))
+                               /* Return with the HPTE still locked */
+                               return (hash << 3) + (i >> 1);
+
+                       /* Unlock and move on */
+                       hpte[i] = v;
+               }
+
+               if (val & HPTE_V_SECONDARY)
+                       break;
+               val |= HPTE_V_SECONDARY;
+               hash = hash ^ HPT_HASH_MASK;
+       }
+       return -1;
+}
+EXPORT_SYMBOL(kvmppc_hv_find_lock_hpte);
+
+/*
+ * Called in real mode to check whether an HPTE not found fault
+ * is due to accessing a paged-out page or an emulated MMIO page,
+ * or if a protection fault is due to accessing a page that the
+ * guest wanted read/write access to but which we made read-only.
+ * Returns a possibly modified status (DSISR) value if not
+ * (i.e. pass the interrupt to the guest),
+ * -1 to pass the fault up to host kernel mode code, -2 to do that
+ * and also load the instruction word (for MMIO emulation),
+ * or 0 if we should make the guest retry the access.
+ */
+long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
+                         unsigned long slb_v, unsigned int status, bool data)
+{
+       struct kvm *kvm = vcpu->kvm;
+       long int index;
+       unsigned long v, r, gr;
+       unsigned long *hpte;
+       unsigned long valid;
+       struct revmap_entry *rev;
+       unsigned long pp, key;
+
+       /* For protection fault, expect to find a valid HPTE */
+       valid = HPTE_V_VALID;
+       if (status & DSISR_NOHPTE)
+               valid |= HPTE_V_ABSENT;
+
+       index = kvmppc_hv_find_lock_hpte(kvm, addr, slb_v, valid);
+       if (index < 0) {
+               if (status & DSISR_NOHPTE)
+                       return status;  /* there really was no HPTE */
+               return 0;               /* for prot fault, HPTE disappeared */
+       }
+       hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+       v = hpte[0] & ~HPTE_V_HVLOCK;
+       r = hpte[1];
+       rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
+       gr = rev->guest_rpte;
+
+       unlock_hpte(hpte, v);
+
+       /* For not found, if the HPTE is valid by now, retry the instruction */
+       if ((status & DSISR_NOHPTE) && (v & HPTE_V_VALID))
+               return 0;
+
+       /* Check access permissions to the page */
+       pp = gr & (HPTE_R_PP0 | HPTE_R_PP);
+       key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
+       status &= ~DSISR_NOHPTE;        /* DSISR_NOHPTE == SRR1_ISI_NOPT */
+       if (!data) {
+               if (gr & (HPTE_R_N | HPTE_R_G))
+                       return status | SRR1_ISI_N_OR_G;
+               if (!hpte_read_permission(pp, slb_v & key))
+                       return status | SRR1_ISI_PROT;
+       } else if (status & DSISR_ISSTORE) {
+               /* check write permission */
+               if (!hpte_write_permission(pp, slb_v & key))
+                       return status | DSISR_PROTFAULT;
+       } else {
+               if (!hpte_read_permission(pp, slb_v & key))
+                       return status | DSISR_PROTFAULT;
+       }
+
+       /* Check storage key, if applicable */
+       if (data && (vcpu->arch.shregs.msr & MSR_DR)) {
+               unsigned int perm = hpte_get_skey_perm(gr, vcpu->arch.amr);
+               if (status & DSISR_ISSTORE)
+                       perm >>= 1;
+               if (perm & 1)
+                       return status | DSISR_KEYFAULT;
+       }
+
+       /* Save HPTE info for virtual-mode handler */
+       vcpu->arch.pgfault_addr = addr;
+       vcpu->arch.pgfault_index = index;
+       vcpu->arch.pgfault_hpte[0] = v;
+       vcpu->arch.pgfault_hpte[1] = r;
+
+       /* Check the storage key to see if it is possibly emulated MMIO */
+       if (data && (vcpu->arch.shregs.msr & MSR_IR) &&
+           (r & (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) ==
+           (HPTE_R_KEY_HI | HPTE_R_KEY_LO))
+               return -2;      /* MMIO emulation - load instr word */
+
+       return -1;              /* send fault up to host kernel mode */
+}
index 5c8b26183f5035a9765443cf440e0b9f46df51f1..b70bf22a3ff39615c90d82c78764f897d4fa1677 100644 (file)
@@ -601,6 +601,30 @@ kvmppc_interrupt:
 
        stw     r12,VCPU_TRAP(r9)
 
+       /* Save HEIR (HV emulation assist reg) in last_inst
+          if this is an HEI (HV emulation interrupt, e40) */
+       li      r3,KVM_INST_FETCH_FAILED
+BEGIN_FTR_SECTION
+       cmpwi   r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
+       bne     11f
+       mfspr   r3,SPRN_HEIR
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+11:    stw     r3,VCPU_LAST_INST(r9)
+
+       /* these are volatile across C function calls */
+       mfctr   r3
+       mfxer   r4
+       std     r3, VCPU_CTR(r9)
+       stw     r4, VCPU_XER(r9)
+
+BEGIN_FTR_SECTION
+       /* If this is a page table miss then see if it's theirs or ours */
+       cmpwi   r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
+       beq     kvmppc_hdsi
+       cmpwi   r12, BOOK3S_INTERRUPT_H_INST_STORAGE
+       beq     kvmppc_hisi
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
        /* See if this is a leftover HDEC interrupt */
        cmpwi   r12,BOOK3S_INTERRUPT_HV_DECREMENTER
        bne     2f
@@ -608,7 +632,7 @@ kvmppc_interrupt:
        cmpwi   r3,0
        bge     ignore_hdec
 2:
-       /* See if this is something we can handle in real mode */
+       /* See if this is an hcall we can handle in real mode */
        cmpwi   r12,BOOK3S_INTERRUPT_SYSCALL
        beq     hcall_try_real_mode
 
@@ -624,6 +648,7 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
+nohpte_cont:
 hcall_real_cont:               /* r9 = vcpu, r12 = trap, r13 = paca */
        /* Save DEC */
        mfspr   r5,SPRN_DEC
@@ -632,36 +657,21 @@ hcall_real_cont:          /* r9 = vcpu, r12 = trap, r13 = paca */
        add     r5,r5,r6
        std     r5,VCPU_DEC_EXPIRES(r9)
 
-       /* Save HEIR (HV emulation assist reg) in last_inst
-          if this is an HEI (HV emulation interrupt, e40) */
-       li      r3,-1
-BEGIN_FTR_SECTION
-       cmpwi   r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
-       bne     11f
-       mfspr   r3,SPRN_HEIR
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-11:    stw     r3,VCPU_LAST_INST(r9)
-
        /* Save more register state  */
-       mfxer   r5
        mfdar   r6
        mfdsisr r7
-       mfctr   r8
-
-       stw     r5, VCPU_XER(r9)
        std     r6, VCPU_DAR(r9)
        stw     r7, VCPU_DSISR(r9)
-       std     r8, VCPU_CTR(r9)
-       /* grab HDAR & HDSISR if HV data storage interrupt (HDSI) */
 BEGIN_FTR_SECTION
+       /* don't overwrite fault_dar/fault_dsisr if HDSI */
        cmpwi   r12,BOOK3S_INTERRUPT_H_DATA_STORAGE
        beq     6f
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-7:     std     r6, VCPU_FAULT_DAR(r9)
+       std     r6, VCPU_FAULT_DAR(r9)
        stw     r7, VCPU_FAULT_DSISR(r9)
 
        /* Save guest CTRL register, set runlatch to 1 */
-       mfspr   r6,SPRN_CTRLF
+6:     mfspr   r6,SPRN_CTRLF
        stw     r6,VCPU_CTRL(r9)
        andi.   r0,r6,1
        bne     4f
@@ -1094,9 +1104,131 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        mtspr   SPRN_HSRR1, r7
        ba      0x500
 
-6:     mfspr   r6,SPRN_HDAR
-       mfspr   r7,SPRN_HDSISR
-       b       7b
+/*
+ * Check whether an HDSI is an HPTE not found fault or something else.
+ * If it is an HPTE not found fault that is due to the guest accessing
+ * a page that they have mapped but which we have paged out, then
+ * we continue on with the guest exit path.  In all other cases,
+ * reflect the HDSI to the guest as a DSI.
+ */
+kvmppc_hdsi:
+       mfspr   r4, SPRN_HDAR
+       mfspr   r6, SPRN_HDSISR
+       /* HPTE not found fault or protection fault? */
+       andis.  r0, r6, (DSISR_NOHPTE | DSISR_PROTFAULT)@h
+       beq     1f                      /* if not, send it to the guest */
+       andi.   r0, r11, MSR_DR         /* data relocation enabled? */
+       beq     3f
+       clrrdi  r0, r4, 28
+       PPC_SLBFEE_DOT(r5, r0)          /* if so, look up SLB */
+       bne     1f                      /* if no SLB entry found */
+4:     std     r4, VCPU_FAULT_DAR(r9)
+       stw     r6, VCPU_FAULT_DSISR(r9)
+
+       /* Search the hash table. */
+       mr      r3, r9                  /* vcpu pointer */
+       li      r7, 1                   /* data fault */
+       bl      .kvmppc_hpte_hv_fault
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       ld      r10, VCPU_PC(r9)
+       ld      r11, VCPU_MSR(r9)
+       li      r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
+       cmpdi   r3, 0                   /* retry the instruction */
+       beq     6f
+       cmpdi   r3, -1                  /* handle in kernel mode */
+       beq     nohpte_cont
+       cmpdi   r3, -2                  /* MMIO emulation; need instr word */
+       beq     2f
+
+       /* Synthesize a DSI for the guest */
+       ld      r4, VCPU_FAULT_DAR(r9)
+       mr      r6, r3
+1:     mtspr   SPRN_DAR, r4
+       mtspr   SPRN_DSISR, r6
+       mtspr   SPRN_SRR0, r10
+       mtspr   SPRN_SRR1, r11
+       li      r10, BOOK3S_INTERRUPT_DATA_STORAGE
+       li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
+       rotldi  r11, r11, 63
+6:     ld      r7, VCPU_CTR(r9)
+       lwz     r8, VCPU_XER(r9)
+       mtctr   r7
+       mtxer   r8
+       mr      r4, r9
+       b       fast_guest_return
+
+3:     ld      r5, VCPU_KVM(r9)        /* not relocated, use VRMA */
+       ld      r5, KVM_VRMA_SLB_V(r5)
+       b       4b
+
+       /* If this is for emulated MMIO, load the instruction word */
+2:     li      r8, KVM_INST_FETCH_FAILED       /* In case lwz faults */
+
+       /* Set guest mode to 'jump over instruction' so if lwz faults
+        * we'll just continue at the next IP. */
+       li      r0, KVM_GUEST_MODE_SKIP
+       stb     r0, HSTATE_IN_GUEST(r13)
+
+       /* Do the access with MSR:DR enabled */
+       mfmsr   r3
+       ori     r4, r3, MSR_DR          /* Enable paging for data */
+       mtmsrd  r4
+       lwz     r8, 0(r10)
+       mtmsrd  r3
+
+       /* Store the result */
+       stw     r8, VCPU_LAST_INST(r9)
+
+       /* Unset guest mode. */
+       li      r0, KVM_GUEST_MODE_NONE
+       stb     r0, HSTATE_IN_GUEST(r13)
+       b       nohpte_cont
+
+/*
+ * Similarly for an HISI, reflect it to the guest as an ISI unless
+ * it is an HPTE not found fault for a page that we have paged out.
+ */
+kvmppc_hisi:
+       andis.  r0, r11, SRR1_ISI_NOPT@h
+       beq     1f
+       andi.   r0, r11, MSR_IR         /* instruction relocation enabled? */
+       beq     3f
+       clrrdi  r0, r10, 28
+       PPC_SLBFEE_DOT(r5, r0)          /* if so, look up SLB */
+       bne     1f                      /* if no SLB entry found */
+4:
+       /* Search the hash table. */
+       mr      r3, r9                  /* vcpu pointer */
+       mr      r4, r10
+       mr      r6, r11
+       li      r7, 0                   /* instruction fault */
+       bl      .kvmppc_hpte_hv_fault
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       ld      r10, VCPU_PC(r9)
+       ld      r11, VCPU_MSR(r9)
+       li      r12, BOOK3S_INTERRUPT_H_INST_STORAGE
+       cmpdi   r3, 0                   /* retry the instruction */
+       beq     6f
+       cmpdi   r3, -1                  /* handle in kernel mode */
+       beq     nohpte_cont
+
+       /* Synthesize an ISI for the guest */
+       mr      r11, r3
+1:     mtspr   SPRN_SRR0, r10
+       mtspr   SPRN_SRR1, r11
+       li      r10, BOOK3S_INTERRUPT_INST_STORAGE
+       li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
+       rotldi  r11, r11, 63
+6:     ld      r7, VCPU_CTR(r9)
+       lwz     r8, VCPU_XER(r9)
+       mtctr   r7
+       mtxer   r8
+       mr      r4, r9
+       b       fast_guest_return
+
+3:     ld      r6, VCPU_KVM(r9)        /* not relocated, use VRMA */
+       ld      r5, KVM_VRMA_SLB_V(r6)
+       b       4b
 
 /*
  * Try to handle an hcall in real mode.
index 7b0ee96c1bedec56a280e90ab47f7cceeba1d692..e70ef2d86431bd7eef8c93adf219a88009ea6828 100644 (file)
@@ -196,7 +196,8 @@ static int kvmppc_emulate_fpr_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
                kvmppc_inject_pf(vcpu, addr, false);
                goto done_load;
        } else if (r == EMULATE_DO_MMIO) {
-               emulated = kvmppc_handle_load(run, vcpu, KVM_REG_FPR | rs, len, 1);
+               emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FPR | rs,
+                                             len, 1);
                goto done_load;
        }
 
@@ -286,11 +287,13 @@ static int kvmppc_emulate_psq_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
                kvmppc_inject_pf(vcpu, addr, false);
                goto done_load;
        } else if ((r == EMULATE_DO_MMIO) && w) {
-               emulated = kvmppc_handle_load(run, vcpu, KVM_REG_FPR | rs, 4, 1);
+               emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FPR | rs,
+                                             4, 1);
                vcpu->arch.qpr[rs] = tmp[1];
                goto done_load;
        } else if (r == EMULATE_DO_MMIO) {
-               emulated = kvmppc_handle_load(run, vcpu, KVM_REG_FQPR | rs, 8, 1);
+               emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FQPR | rs,
+                                             8, 1);
                goto done_load;
        }
 
index 220fcdf26978efbf3bfd485772cfd7fb2453519b..7340e1090b770302cdb055728b0c7740241c0ca6 100644 (file)
@@ -51,15 +51,19 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 #define MSR_USER32 MSR_USER
 #define MSR_USER64 MSR_USER
 #define HW_PAGE_SIZE PAGE_SIZE
+#define __hard_irq_disable local_irq_disable
+#define __hard_irq_enable local_irq_enable
 #endif
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
-       memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_svcpu(vcpu)->slb));
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu,
               sizeof(get_paca()->shadow_vcpu));
-       to_svcpu(vcpu)->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu_put(svcpu);
 #endif
 
 #ifdef CONFIG_PPC_BOOK3S_32
@@ -70,10 +74,12 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
-       memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_svcpu(vcpu)->slb));
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
               sizeof(get_paca()->shadow_vcpu));
-       to_book3s(vcpu)->slb_shadow_max = to_svcpu(vcpu)->slb_max;
+       to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
+       svcpu_put(svcpu);
 #endif
 
        kvmppc_giveup_ext(vcpu, MSR_FP);
@@ -151,14 +157,16 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
 #ifdef CONFIG_PPC_BOOK3S_64
        if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
                kvmppc_mmu_book3s_64_init(vcpu);
-               to_book3s(vcpu)->hior = 0xfff00000;
+               if (!to_book3s(vcpu)->hior_explicit)
+                       to_book3s(vcpu)->hior = 0xfff00000;
                to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_64;
        } else
 #endif
        {
                kvmppc_mmu_book3s_32_init(vcpu);
-               to_book3s(vcpu)->hior = 0;
+               if (!to_book3s(vcpu)->hior_explicit)
+                       to_book3s(vcpu)->hior = 0;
                to_book3s(vcpu)->msr_mask = 0xffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_32;
        }
@@ -308,19 +316,22 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        if (page_found == -ENOENT) {
                /* Page not found in guest PTE entries */
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
                vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-               vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+               vcpu->arch.shared->dsisr = svcpu->fault_dsisr;
                vcpu->arch.shared->msr |=
-                       (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+                       (svcpu->shadow_srr1 & 0x00000000f8000000ULL);
+               svcpu_put(svcpu);
                kvmppc_book3s_queue_irqprio(vcpu, vec);
        } else if (page_found == -EPERM) {
                /* Storage protection */
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
                vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-               vcpu->arch.shared->dsisr =
-                       to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
+               vcpu->arch.shared->dsisr = svcpu->fault_dsisr & ~DSISR_NOHPTE;
                vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
                vcpu->arch.shared->msr |=
-                       (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+                       svcpu->shadow_srr1 & 0x00000000f8000000ULL;
+               svcpu_put(svcpu);
                kvmppc_book3s_queue_irqprio(vcpu, vec);
        } else if (page_found == -EINVAL) {
                /* Page not found in guest SLB */
@@ -517,24 +528,29 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
        run->ready_for_interrupt_injection = 1;
 
        trace_kvm_book3s_exit(exit_nr, vcpu);
+       preempt_enable();
        kvm_resched(vcpu);
        switch (exit_nr) {
        case BOOK3S_INTERRUPT_INST_STORAGE:
+       {
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               ulong shadow_srr1 = svcpu->shadow_srr1;
                vcpu->stat.pf_instruc++;
 
 #ifdef CONFIG_PPC_BOOK3S_32
                /* We set segments as unused segments when invalidating them. So
                 * treat the respective fault as segment fault. */
-               if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
-                   == SR_INVALID) {
+               if (svcpu->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT] == SR_INVALID) {
                        kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
                        r = RESUME_GUEST;
+                       svcpu_put(svcpu);
                        break;
                }
 #endif
+               svcpu_put(svcpu);
 
                /* only care about PTEG not found errors, but leave NX alone */
-               if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
+               if (shadow_srr1 & 0x40000000) {
                        r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
                        vcpu->stat.sp_instruc++;
                } else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
@@ -547,33 +563,37 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
                        r = RESUME_GUEST;
                } else {
-                       vcpu->arch.shared->msr |=
-                               to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+                       vcpu->arch.shared->msr |= shadow_srr1 & 0x58000000;
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                        r = RESUME_GUEST;
                }
                break;
+       }
        case BOOK3S_INTERRUPT_DATA_STORAGE:
        {
                ulong dar = kvmppc_get_fault_dar(vcpu);
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               u32 fault_dsisr = svcpu->fault_dsisr;
                vcpu->stat.pf_storage++;
 
 #ifdef CONFIG_PPC_BOOK3S_32
                /* We set segments as unused segments when invalidating them. So
                 * treat the respective fault as segment fault. */
-               if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
+               if ((svcpu->sr[dar >> SID_SHIFT]) == SR_INVALID) {
                        kvmppc_mmu_map_segment(vcpu, dar);
                        r = RESUME_GUEST;
+                       svcpu_put(svcpu);
                        break;
                }
 #endif
+               svcpu_put(svcpu);
 
                /* The only case we need to handle is missing shadow PTEs */
-               if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
+               if (fault_dsisr & DSISR_NOHPTE) {
                        r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
                } else {
                        vcpu->arch.shared->dar = dar;
-                       vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+                       vcpu->arch.shared->dsisr = fault_dsisr;
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                        r = RESUME_GUEST;
                }
@@ -609,10 +629,13 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
        case BOOK3S_INTERRUPT_PROGRAM:
        {
                enum emulation_result er;
+               struct kvmppc_book3s_shadow_vcpu *svcpu;
                ulong flags;
 
 program_interrupt:
-               flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
+               svcpu = svcpu_get(vcpu);
+               flags = svcpu->shadow_srr1 & 0x1f0000ull;
+               svcpu_put(svcpu);
 
                if (vcpu->arch.shared->msr & MSR_PR) {
 #ifdef EXIT_DEBUG
@@ -740,20 +763,33 @@ program_interrupt:
                r = RESUME_GUEST;
                break;
        default:
+       {
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               ulong shadow_srr1 = svcpu->shadow_srr1;
+               svcpu_put(svcpu);
                /* Ugh - bork here! What did we get? */
                printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
-                       exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1);
+                       exit_nr, kvmppc_get_pc(vcpu), shadow_srr1);
                r = RESUME_HOST;
                BUG();
                break;
        }
-
+       }
 
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
                 * we aren't already exiting to userspace for some other
                 * reason. */
+
+               /*
+                * Interrupts could be timers for the guest which we have to
+                * inject again, so let's postpone them until we're in the guest
+                * and if we really did time things so badly, then we just exit
+                * again due to a host external interrupt.
+                */
+               __hard_irq_disable();
                if (signal_pending(current)) {
+                       __hard_irq_enable();
 #ifdef EXIT_DEBUG
                        printk(KERN_EMERG "KVM: Going back to host\n");
 #endif
@@ -761,10 +797,12 @@ program_interrupt:
                        run->exit_reason = KVM_EXIT_INTR;
                        r = -EINTR;
                } else {
+                       preempt_disable();
+
                        /* In case an interrupt came in that was triggered
                         * from userspace (like DEC), we need to check what
                         * to inject now! */
-                       kvmppc_core_deliver_interrupts(vcpu);
+                       kvmppc_core_prepare_to_enter(vcpu);
                }
        }
 
@@ -836,6 +874,38 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               if (!r)
+                       to_book3s(vcpu)->hior_explicit = true;
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
        return 0;
@@ -923,16 +993,31 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
        ulong ext_msr;
 
+       preempt_disable();
+
        /* Check if we can run the vcpu at all */
        if (!vcpu->arch.sane) {
                kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
+       kvmppc_core_prepare_to_enter(vcpu);
+
+       /*
+        * Interrupts could be timers for the guest which we have to inject
+        * again, so let's postpone them until we're in the guest and if we
+        * really did time things so badly, then we just exit again due to
+        * a host external interrupt.
+        */
+       __hard_irq_disable();
+
        /* No need to go into the guest when all we do is going out */
        if (signal_pending(current)) {
+               __hard_irq_enable();
                kvm_run->exit_reason = KVM_EXIT_INTR;
-               return -EINTR;
+               ret = -EINTR;
+               goto out;
        }
 
        /* Save FPU state in stack */
@@ -974,8 +1059,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        kvm_guest_exit();
 
-       local_irq_disable();
-
        current->thread.regs->msr = ext_msr;
 
        /* Make sure we save the guest FPU/Altivec/VSX state */
@@ -1002,9 +1085,50 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        current->thread.used_vsr = used_vsr;
 #endif
 
+out:
+       preempt_enable();
        return ret;
 }
 
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+                                     struct kvm_dirty_log *log)
+{
+       struct kvm_memory_slot *memslot;
+       struct kvm_vcpu *vcpu;
+       ulong ga, ga_end;
+       int is_dirty = 0;
+       int r;
+       unsigned long n;
+
+       mutex_lock(&kvm->slots_lock);
+
+       r = kvm_get_dirty_log(kvm, log, &is_dirty);
+       if (r)
+               goto out;
+
+       /* If nothing is dirty, don't bother messing with page tables. */
+       if (is_dirty) {
+               memslot = id_to_memslot(kvm->memslots, log->slot);
+
+               ga = memslot->base_gfn << PAGE_SHIFT;
+               ga_end = ga + (memslot->npages << PAGE_SHIFT);
+
+               kvm_for_each_vcpu(n, vcpu, kvm)
+                       kvmppc_mmu_pte_pflush(vcpu, ga, ga_end);
+
+               n = kvm_dirty_bitmap_bytes(memslot);
+               memset(memslot->dirty_bitmap, 0, n);
+       }
+
+       r = 0;
+out:
+       mutex_unlock(&kvm->slots_lock);
+       return r;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
                                      struct kvm_userspace_memory_region *mem)
 {
index bb6c988f010aa29b0732d628788547456e6b577c..ee9e1ee9c858116aad1256e35fd27f61eb749994 100644 (file)
@@ -124,12 +124,6 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
        vcpu->arch.shared->msr = new_msr;
 
        kvmppc_mmu_msr_notify(vcpu, old_msr);
-
-       if (vcpu->arch.shared->msr & MSR_WE) {
-               kvm_vcpu_block(vcpu);
-               kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
-       };
-
        kvmppc_vcpu_sync_spe(vcpu);
 }
 
@@ -258,9 +252,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                allowed = vcpu->arch.shared->msr & MSR_ME;
                msr_mask = 0;
                break;
-       case BOOKE_IRQPRIO_EXTERNAL:
        case BOOKE_IRQPRIO_DECREMENTER:
        case BOOKE_IRQPRIO_FIT:
+               keep_irq = true;
+               /* fall through */
+       case BOOKE_IRQPRIO_EXTERNAL:
                allowed = vcpu->arch.shared->msr & MSR_EE;
                allowed = allowed && !crit;
                msr_mask = MSR_CE|MSR_ME|MSR_DE;
@@ -276,7 +272,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                vcpu->arch.shared->srr1 = vcpu->arch.shared->msr;
                vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
                if (update_esr == true)
-                       vcpu->arch.esr = vcpu->arch.queued_esr;
+                       vcpu->arch.shared->esr = vcpu->arch.queued_esr;
                if (update_dear == true)
                        vcpu->arch.shared->dar = vcpu->arch.queued_dear;
                kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
@@ -288,13 +284,26 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
        return allowed;
 }
 
-/* Check pending exceptions and deliver one, if possible. */
-void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
+static void update_timer_ints(struct kvm_vcpu *vcpu)
+{
+       if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
+               kvmppc_core_queue_dec(vcpu);
+       else
+               kvmppc_core_dequeue_dec(vcpu);
+}
+
+static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
 {
        unsigned long *pending = &vcpu->arch.pending_exceptions;
-       unsigned long old_pending = vcpu->arch.pending_exceptions;
        unsigned int priority;
 
+       if (vcpu->requests) {
+               if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
+                       smp_mb();
+                       update_timer_ints(vcpu);
+               }
+       }
+
        priority = __ffs(*pending);
        while (priority <= BOOKE_IRQPRIO_MAX) {
                if (kvmppc_booke_irqprio_deliver(vcpu, priority))
@@ -306,10 +315,24 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
        }
 
        /* Tell the guest about our interrupt status */
-       if (*pending)
-               vcpu->arch.shared->int_pending = 1;
-       else if (old_pending)
-               vcpu->arch.shared->int_pending = 0;
+       vcpu->arch.shared->int_pending = !!*pending;
+}
+
+/* Check pending exceptions and deliver one, if possible. */
+void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
+{
+       WARN_ON_ONCE(!irqs_disabled());
+
+       kvmppc_core_check_exceptions(vcpu);
+
+       if (vcpu->arch.shared->msr & MSR_WE) {
+               local_irq_enable();
+               kvm_vcpu_block(vcpu);
+               local_irq_disable();
+
+               kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
+               kvmppc_core_check_exceptions(vcpu);
+       };
 }
 
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
@@ -322,11 +345,21 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        }
 
        local_irq_disable();
+
+       kvmppc_core_prepare_to_enter(vcpu);
+
+       if (signal_pending(current)) {
+               kvm_run->exit_reason = KVM_EXIT_INTR;
+               ret = -EINTR;
+               goto out;
+       }
+
        kvm_guest_enter();
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
        kvm_guest_exit();
-       local_irq_enable();
 
+out:
+       local_irq_enable();
        return ret;
 }
 
@@ -603,7 +636,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        local_irq_disable();
 
-       kvmppc_core_deliver_interrupts(vcpu);
+       kvmppc_core_prepare_to_enter(vcpu);
 
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
@@ -628,6 +661,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.pc = 0;
        vcpu->arch.shared->msr = 0;
        vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS;
+       vcpu->arch.shared->pir = vcpu->vcpu_id;
        kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
 
        vcpu->arch.shadow_pid = 1;
@@ -662,10 +696,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        regs->sprg1 = vcpu->arch.shared->sprg1;
        regs->sprg2 = vcpu->arch.shared->sprg2;
        regs->sprg3 = vcpu->arch.shared->sprg3;
-       regs->sprg4 = vcpu->arch.sprg4;
-       regs->sprg5 = vcpu->arch.sprg5;
-       regs->sprg6 = vcpu->arch.sprg6;
-       regs->sprg7 = vcpu->arch.sprg7;
+       regs->sprg4 = vcpu->arch.shared->sprg4;
+       regs->sprg5 = vcpu->arch.shared->sprg5;
+       regs->sprg6 = vcpu->arch.shared->sprg6;
+       regs->sprg7 = vcpu->arch.shared->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -690,10 +724,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        vcpu->arch.shared->sprg1 = regs->sprg1;
        vcpu->arch.shared->sprg2 = regs->sprg2;
        vcpu->arch.shared->sprg3 = regs->sprg3;
-       vcpu->arch.sprg4 = regs->sprg4;
-       vcpu->arch.sprg5 = regs->sprg5;
-       vcpu->arch.sprg6 = regs->sprg6;
-       vcpu->arch.sprg7 = regs->sprg7;
+       vcpu->arch.shared->sprg4 = regs->sprg4;
+       vcpu->arch.shared->sprg5 = regs->sprg5;
+       vcpu->arch.shared->sprg6 = regs->sprg6;
+       vcpu->arch.shared->sprg7 = regs->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -711,7 +745,7 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
        sregs->u.e.csrr0 = vcpu->arch.csrr0;
        sregs->u.e.csrr1 = vcpu->arch.csrr1;
        sregs->u.e.mcsr = vcpu->arch.mcsr;
-       sregs->u.e.esr = vcpu->arch.esr;
+       sregs->u.e.esr = vcpu->arch.shared->esr;
        sregs->u.e.dear = vcpu->arch.shared->dar;
        sregs->u.e.tsr = vcpu->arch.tsr;
        sregs->u.e.tcr = vcpu->arch.tcr;
@@ -729,28 +763,19 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
        vcpu->arch.csrr0 = sregs->u.e.csrr0;
        vcpu->arch.csrr1 = sregs->u.e.csrr1;
        vcpu->arch.mcsr = sregs->u.e.mcsr;
-       vcpu->arch.esr = sregs->u.e.esr;
+       vcpu->arch.shared->esr = sregs->u.e.esr;
        vcpu->arch.shared->dar = sregs->u.e.dear;
        vcpu->arch.vrsave = sregs->u.e.vrsave;
-       vcpu->arch.tcr = sregs->u.e.tcr;
+       kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
 
-       if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC)
+       if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC) {
                vcpu->arch.dec = sregs->u.e.dec;
-
-       kvmppc_emulate_dec(vcpu);
+               kvmppc_emulate_dec(vcpu);
+       }
 
        if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
-               /*
-                * FIXME: existing KVM timer handling is incomplete.
-                * TSR cannot be read by the guest, and its value in
-                * vcpu->arch is always zero.  For now, just handle
-                * the case where the caller is trying to inject a
-                * decrementer interrupt.
-                */
-
-               if ((sregs->u.e.tsr & TSR_DIS) &&
-                   (vcpu->arch.tcr & TCR_DIE))
-                       kvmppc_core_queue_dec(vcpu);
+               vcpu->arch.tsr = sregs->u.e.tsr;
+               update_timer_ints(vcpu);
        }
 
        return 0;
@@ -761,7 +786,7 @@ static void get_sregs_arch206(struct kvm_vcpu *vcpu,
 {
        sregs->u.e.features |= KVM_SREGS_E_ARCH206;
 
-       sregs->u.e.pir = 0;
+       sregs->u.e.pir = vcpu->vcpu_id;
        sregs->u.e.mcsrr0 = vcpu->arch.mcsrr0;
        sregs->u.e.mcsrr1 = vcpu->arch.mcsrr1;
        sregs->u.e.decar = vcpu->arch.decar;
@@ -774,7 +799,7 @@ static int set_sregs_arch206(struct kvm_vcpu *vcpu,
        if (!(sregs->u.e.features & KVM_SREGS_E_ARCH206))
                return 0;
 
-       if (sregs->u.e.pir != 0)
+       if (sregs->u.e.pir != vcpu->vcpu_id)
                return -EINVAL;
 
        vcpu->arch.mcsrr0 = sregs->u.e.mcsrr0;
@@ -862,6 +887,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return kvmppc_core_set_sregs(vcpu, sregs);
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       return -EINVAL;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       return -EINVAL;
+}
+
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        return -ENOTSUPP;
@@ -906,6 +941,33 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
 }
 
+void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
+{
+       vcpu->arch.tcr = new_tcr;
+       update_timer_ints(vcpu);
+}
+
+void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
+{
+       set_bits(tsr_bits, &vcpu->arch.tsr);
+       smp_wmb();
+       kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+       kvm_vcpu_kick(vcpu);
+}
+
+void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
+{
+       clear_bits(tsr_bits, &vcpu->arch.tsr);
+       update_timer_ints(vcpu);
+}
+
+void kvmppc_decrementer_func(unsigned long data)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+
+       kvmppc_set_tsr_bits(vcpu, TSR_DIS);
+}
+
 int __init kvmppc_booke_init(void)
 {
        unsigned long ivor[16];
index 8e1fe33d64e596ab32bb8bcbbb1f65c590fc4c37..2fe202705a3f9c4677f7334885233f50bb5a2942 100644 (file)
@@ -55,6 +55,10 @@ extern unsigned long kvmppc_booke_handlers;
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
 void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
 
+void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr);
+void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
+void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
+
 int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                             unsigned int inst, int *advance);
 int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt);
index 1260f5f24c0c3df9827a4d08131ad589ee83d170..3e652da365348433ce1ae2dc7cbe206b8e7e4e32 100644 (file)
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright IBM Corp. 2008
+ * Copyright 2011 Freescale Semiconductor, Inc.
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
@@ -107,7 +108,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
        case SPRN_DEAR:
                vcpu->arch.shared->dar = spr_val; break;
        case SPRN_ESR:
-               vcpu->arch.esr = spr_val; break;
+               vcpu->arch.shared->esr = spr_val; break;
        case SPRN_DBCR0:
                vcpu->arch.dbcr0 = spr_val; break;
        case SPRN_DBCR1:
@@ -115,23 +116,23 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
        case SPRN_DBSR:
                vcpu->arch.dbsr &= ~spr_val; break;
        case SPRN_TSR:
-               vcpu->arch.tsr &= ~spr_val; break;
+               kvmppc_clr_tsr_bits(vcpu, spr_val);
+               break;
        case SPRN_TCR:
-               vcpu->arch.tcr = spr_val;
-               kvmppc_emulate_dec(vcpu);
+               kvmppc_set_tcr(vcpu, spr_val);
                break;
 
        /* Note: SPRG4-7 are user-readable. These values are
         * loaded into the real SPRGs when resuming the
         * guest. */
        case SPRN_SPRG4:
-               vcpu->arch.sprg4 = spr_val; break;
+               vcpu->arch.shared->sprg4 = spr_val; break;
        case SPRN_SPRG5:
-               vcpu->arch.sprg5 = spr_val; break;
+               vcpu->arch.shared->sprg5 = spr_val; break;
        case SPRN_SPRG6:
-               vcpu->arch.sprg6 = spr_val; break;
+               vcpu->arch.shared->sprg6 = spr_val; break;
        case SPRN_SPRG7:
-               vcpu->arch.sprg7 = spr_val; break;
+               vcpu->arch.shared->sprg7 = spr_val; break;
 
        case SPRN_IVPR:
                vcpu->arch.ivpr = spr_val;
@@ -202,13 +203,17 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
        case SPRN_DEAR:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break;
        case SPRN_ESR:
-               kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->esr); break;
        case SPRN_DBCR0:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr0); break;
        case SPRN_DBCR1:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr1); break;
        case SPRN_DBSR:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbsr); break;
+       case SPRN_TSR:
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.tsr); break;
+       case SPRN_TCR:
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.tcr); break;
 
        case SPRN_IVOR0:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
index 42f2fb1f66e9dc1bad51b44334dca63fc29d8365..10d8ef602e5c9303795c7b78268d5691be79eeec 100644 (file)
@@ -402,19 +402,25 @@ lightweight_exit:
        /* Save vcpu pointer for the exception handlers. */
        mtspr   SPRN_SPRG_WVCPU, r4
 
+       lwz     r5, VCPU_SHARED(r4)
+
        /* Can't switch the stack pointer until after IVPR is switched,
         * because host interrupt handlers would get confused. */
        lwz     r1, VCPU_GPR(r1)(r4)
 
-       /* Host interrupt handlers may have clobbered these guest-readable
-        * SPRGs, so we need to reload them here with the guest's values. */
-       lwz     r3, VCPU_SPRG4(r4)
+       /*
+        * Host interrupt handlers may have clobbered these
+        * guest-readable SPRGs, or the guest kernel may have
+        * written directly to the shared area, so we
+        * need to reload them here with the guest's values.
+        */
+       lwz     r3, VCPU_SHARED_SPRG4(r5)
        mtspr   SPRN_SPRG4W, r3
-       lwz     r3, VCPU_SPRG5(r4)
+       lwz     r3, VCPU_SHARED_SPRG5(r5)
        mtspr   SPRN_SPRG5W, r3
-       lwz     r3, VCPU_SPRG6(r4)
+       lwz     r3, VCPU_SHARED_SPRG6(r5)
        mtspr   SPRN_SPRG6W, r3
-       lwz     r3, VCPU_SPRG7(r4)
+       lwz     r3, VCPU_SHARED_SPRG7(r5)
        mtspr   SPRN_SPRG7W, r3
 
 #ifdef CONFIG_KVM_EXIT_TIMING
index 8c0d45a6faf7f49db9aef9c9a495c1ef20d155d8..ddcd896fa2ffee16d037c7ecedb839e3d24741a5 100644 (file)
@@ -71,9 +71,6 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.pvr = mfspr(SPRN_PVR);
        vcpu_e500->svr = mfspr(SPRN_SVR);
 
-       /* Since booke kvm only support one core, update all vcpus' PIR to 0 */
-       vcpu->vcpu_id = 0;
-
        vcpu->arch.cpu_type = KVM_CPU_E500V2;
 
        return 0;
@@ -118,12 +115,12 @@ void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
        sregs->u.e.impl.fsl.hid0 = vcpu_e500->hid0;
        sregs->u.e.impl.fsl.mcar = vcpu_e500->mcar;
 
-       sregs->u.e.mas0 = vcpu_e500->mas0;
-       sregs->u.e.mas1 = vcpu_e500->mas1;
-       sregs->u.e.mas2 = vcpu_e500->mas2;
-       sregs->u.e.mas7_3 = ((u64)vcpu_e500->mas7 << 32) | vcpu_e500->mas3;
-       sregs->u.e.mas4 = vcpu_e500->mas4;
-       sregs->u.e.mas6 = vcpu_e500->mas6;
+       sregs->u.e.mas0 = vcpu->arch.shared->mas0;
+       sregs->u.e.mas1 = vcpu->arch.shared->mas1;
+       sregs->u.e.mas2 = vcpu->arch.shared->mas2;
+       sregs->u.e.mas7_3 = vcpu->arch.shared->mas7_3;
+       sregs->u.e.mas4 = vcpu->arch.shared->mas4;
+       sregs->u.e.mas6 = vcpu->arch.shared->mas6;
 
        sregs->u.e.mmucfg = mfspr(SPRN_MMUCFG);
        sregs->u.e.tlbcfg[0] = vcpu_e500->tlb0cfg;
@@ -151,13 +148,12 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
        }
 
        if (sregs->u.e.features & KVM_SREGS_E_ARCH206_MMU) {
-               vcpu_e500->mas0 = sregs->u.e.mas0;
-               vcpu_e500->mas1 = sregs->u.e.mas1;
-               vcpu_e500->mas2 = sregs->u.e.mas2;
-               vcpu_e500->mas7 = sregs->u.e.mas7_3 >> 32;
-               vcpu_e500->mas3 = (u32)sregs->u.e.mas7_3;
-               vcpu_e500->mas4 = sregs->u.e.mas4;
-               vcpu_e500->mas6 = sregs->u.e.mas6;
+               vcpu->arch.shared->mas0 = sregs->u.e.mas0;
+               vcpu->arch.shared->mas1 = sregs->u.e.mas1;
+               vcpu->arch.shared->mas2 = sregs->u.e.mas2;
+               vcpu->arch.shared->mas7_3 = sregs->u.e.mas7_3;
+               vcpu->arch.shared->mas4 = sregs->u.e.mas4;
+               vcpu->arch.shared->mas6 = sregs->u.e.mas6;
        }
 
        if (!(sregs->u.e.features & KVM_SREGS_E_IVOR))
@@ -233,6 +229,10 @@ static int __init kvmppc_e500_init(void)
        unsigned long ivor[3];
        unsigned long max_ivor = 0;
 
+       r = kvmppc_core_check_processor_compat();
+       if (r)
+               return r;
+
        r = kvmppc_booke_init();
        if (r)
                return r;
index d48ae396f41e96ab9f27996fd16fe42046e3227c..6d0b2bd54fb0a9ffef74f3bfb21b04fa34aa4ce7 100644 (file)
@@ -89,19 +89,23 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
                        return EMULATE_FAIL;
                vcpu_e500->pid[2] = spr_val; break;
        case SPRN_MAS0:
-               vcpu_e500->mas0 = spr_val; break;
+               vcpu->arch.shared->mas0 = spr_val; break;
        case SPRN_MAS1:
-               vcpu_e500->mas1 = spr_val; break;
+               vcpu->arch.shared->mas1 = spr_val; break;
        case SPRN_MAS2:
-               vcpu_e500->mas2 = spr_val; break;
+               vcpu->arch.shared->mas2 = spr_val; break;
        case SPRN_MAS3:
-               vcpu_e500->mas3 = spr_val; break;
+               vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff;
+               vcpu->arch.shared->mas7_3 |= spr_val;
+               break;
        case SPRN_MAS4:
-               vcpu_e500->mas4 = spr_val; break;
+               vcpu->arch.shared->mas4 = spr_val; break;
        case SPRN_MAS6:
-               vcpu_e500->mas6 = spr_val; break;
+               vcpu->arch.shared->mas6 = spr_val; break;
        case SPRN_MAS7:
-               vcpu_e500->mas7 = spr_val; break;
+               vcpu->arch.shared->mas7_3 &= (u64)0xffffffff;
+               vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32;
+               break;
        case SPRN_L1CSR0:
                vcpu_e500->l1csr0 = spr_val;
                vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
@@ -143,6 +147,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int emulated = EMULATE_DONE;
+       unsigned long val;
 
        switch (sprn) {
        case SPRN_PID:
@@ -152,20 +157,23 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
        case SPRN_PID2:
                kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break;
        case SPRN_MAS0:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas0); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas0); break;
        case SPRN_MAS1:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas1); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas1); break;
        case SPRN_MAS2:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas2); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas2); break;
        case SPRN_MAS3:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas3); break;
+               val = (u32)vcpu->arch.shared->mas7_3;
+               kvmppc_set_gpr(vcpu, rt, val);
+               break;
        case SPRN_MAS4:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas4); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas4); break;
        case SPRN_MAS6:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas6); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas6); break;
        case SPRN_MAS7:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas7); break;
-
+               val = vcpu->arch.shared->mas7_3 >> 32;
+               kvmppc_set_gpr(vcpu, rt, val);
+               break;
        case SPRN_TLB0CFG:
                kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb0cfg); break;
        case SPRN_TLB1CFG:
index 13c432ea2fa8337ce52667c7c8bd51798a182537..6e53e4164de195583a138c7de853f89a94746c97 100644 (file)
  * published by the Free Software Foundation.
  */
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/highmem.h>
+#include <linux/log2.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/rwsem.h>
+#include <linux/vmalloc.h>
+#include <linux/hugetlb.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_e500.h>
 
@@ -26,7 +33,7 @@
 #include "trace.h"
 #include "timing.h"
 
-#define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1)
+#define to_htlb1_esel(esel) (host_tlb_params[1].entries - (esel) - 1)
 
 struct id {
        unsigned long val;
@@ -63,7 +70,14 @@ static DEFINE_PER_CPU(struct pcpu_id_table, pcpu_sids);
  * The valid range of shadow ID is [1..255] */
 static DEFINE_PER_CPU(unsigned long, pcpu_last_used_sid);
 
-static unsigned int tlb1_entry_num;
+static struct kvmppc_e500_tlb_params host_tlb_params[E500_TLB_NUM];
+
+static struct kvm_book3e_206_tlb_entry *get_entry(
+       struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel, int entry)
+{
+       int offset = vcpu_e500->gtlb_offset[tlbsel];
+       return &vcpu_e500->gtlb_arch[offset + entry];
+}
 
 /*
  * Allocate a free shadow id and setup a valid sid mapping in given entry.
@@ -116,13 +130,11 @@ static inline int local_sid_lookup(struct id *entry)
        return -1;
 }
 
-/* Invalidate all id mappings on local core */
+/* Invalidate all id mappings on local core -- call with preempt disabled */
 static inline void local_sid_destroy_all(void)
 {
-       preempt_disable();
        __get_cpu_var(pcpu_last_used_sid) = 0;
        memset(&__get_cpu_var(pcpu_sids), 0, sizeof(__get_cpu_var(pcpu_sids)));
-       preempt_enable();
 }
 
 static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -218,34 +230,13 @@ void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *vcpu_e500)
        preempt_enable();
 }
 
-void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
-{
-       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe *tlbe;
-       int i, tlbsel;
-
-       printk("| %8s | %8s | %8s | %8s | %8s |\n",
-                       "nr", "mas1", "mas2", "mas3", "mas7");
-
-       for (tlbsel = 0; tlbsel < 2; tlbsel++) {
-               printk("Guest TLB%d:\n", tlbsel);
-               for (i = 0; i < vcpu_e500->gtlb_size[tlbsel]; i++) {
-                       tlbe = &vcpu_e500->gtlb_arch[tlbsel][i];
-                       if (tlbe->mas1 & MAS1_VALID)
-                               printk(" G[%d][%3d] |  %08X | %08X | %08X | %08X |\n",
-                                       tlbsel, i, tlbe->mas1, tlbe->mas2,
-                                       tlbe->mas3, tlbe->mas7);
-               }
-       }
-}
-
-static inline unsigned int tlb0_get_next_victim(
+static inline unsigned int gtlb0_get_next_victim(
                struct kvmppc_vcpu_e500 *vcpu_e500)
 {
        unsigned int victim;
 
        victim = vcpu_e500->gtlb_nv[0]++;
-       if (unlikely(vcpu_e500->gtlb_nv[0] >= KVM_E500_TLB0_WAY_NUM))
+       if (unlikely(vcpu_e500->gtlb_nv[0] >= vcpu_e500->gtlb_params[0].ways))
                vcpu_e500->gtlb_nv[0] = 0;
 
        return victim;
@@ -254,12 +245,12 @@ static inline unsigned int tlb0_get_next_victim(
 static inline unsigned int tlb1_max_shadow_size(void)
 {
        /* reserve one entry for magic page */
-       return tlb1_entry_num - tlbcam_index - 1;
+       return host_tlb_params[1].entries - tlbcam_index - 1;
 }
 
-static inline int tlbe_is_writable(struct tlbe *tlbe)
+static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
 {
-       return tlbe->mas3 & (MAS3_SW|MAS3_UW);
+       return tlbe->mas7_3 & (MAS3_SW|MAS3_UW);
 }
 
 static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode)
@@ -290,40 +281,66 @@ static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
 /*
  * writing shadow tlb entry to host TLB
  */
-static inline void __write_host_tlbe(struct tlbe *stlbe, uint32_t mas0)
+static inline void __write_host_tlbe(struct kvm_book3e_206_tlb_entry *stlbe,
+                                    uint32_t mas0)
 {
        unsigned long flags;
 
        local_irq_save(flags);
        mtspr(SPRN_MAS0, mas0);
        mtspr(SPRN_MAS1, stlbe->mas1);
-       mtspr(SPRN_MAS2, stlbe->mas2);
-       mtspr(SPRN_MAS3, stlbe->mas3);
-       mtspr(SPRN_MAS7, stlbe->mas7);
+       mtspr(SPRN_MAS2, (unsigned long)stlbe->mas2);
+       mtspr(SPRN_MAS3, (u32)stlbe->mas7_3);
+       mtspr(SPRN_MAS7, (u32)(stlbe->mas7_3 >> 32));
        asm volatile("isync; tlbwe" : : : "memory");
        local_irq_restore(flags);
+
+       trace_kvm_booke206_stlb_write(mas0, stlbe->mas8, stlbe->mas1,
+                                     stlbe->mas2, stlbe->mas7_3);
+}
+
+/*
+ * Acquire a mas0 with victim hint, as if we just took a TLB miss.
+ *
+ * We don't care about the address we're searching for, other than that it's
+ * in the right set and is not present in the TLB.  Using a zero PID and a
+ * userspace address means we don't have to set and then restore MAS5, or
+ * calculate a proper MAS6 value.
+ */
+static u32 get_host_mas0(unsigned long eaddr)
+{
+       unsigned long flags;
+       u32 mas0;
+
+       local_irq_save(flags);
+       mtspr(SPRN_MAS6, 0);
+       asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET));
+       mas0 = mfspr(SPRN_MAS0);
+       local_irq_restore(flags);
+
+       return mas0;
 }
 
+/* sesel is for tlb1 only */
 static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
-               int tlbsel, int esel, struct tlbe *stlbe)
+               int tlbsel, int sesel, struct kvm_book3e_206_tlb_entry *stlbe)
 {
+       u32 mas0;
+
        if (tlbsel == 0) {
-               __write_host_tlbe(stlbe,
-                                 MAS0_TLBSEL(0) |
-                                 MAS0_ESEL(esel & (KVM_E500_TLB0_WAY_NUM - 1)));
+               mas0 = get_host_mas0(stlbe->mas2);
+               __write_host_tlbe(stlbe, mas0);
        } else {
                __write_host_tlbe(stlbe,
                                  MAS0_TLBSEL(1) |
-                                 MAS0_ESEL(to_htlb1_esel(esel)));
+                                 MAS0_ESEL(to_htlb1_esel(sesel)));
        }
-       trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
-                            stlbe->mas3, stlbe->mas7);
 }
 
 void kvmppc_map_magic(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe magic;
+       struct kvm_book3e_206_tlb_entry magic;
        ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
        unsigned int stid;
        pfn_t pfn;
@@ -337,9 +354,9 @@ void kvmppc_map_magic(struct kvm_vcpu *vcpu)
        magic.mas1 = MAS1_VALID | MAS1_TS | MAS1_TID(stid) |
                     MAS1_TSIZE(BOOK3E_PAGESZ_4K);
        magic.mas2 = vcpu->arch.magic_page_ea | MAS2_M;
-       magic.mas3 = (pfn << PAGE_SHIFT) |
-                    MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
-       magic.mas7 = pfn >> (32 - PAGE_SHIFT);
+       magic.mas7_3 = ((u64)pfn << PAGE_SHIFT) |
+                      MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
+       magic.mas8 = 0;
 
        __write_host_tlbe(&magic, MAS0_TLBSEL(1) | MAS0_ESEL(tlbcam_index));
        preempt_enable();
@@ -357,10 +374,11 @@ void kvmppc_e500_tlb_put(struct kvm_vcpu *vcpu)
 {
 }
 
-static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
-                                        int tlbsel, int esel)
+static void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500,
+                               int tlbsel, int esel)
 {
-       struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       struct kvm_book3e_206_tlb_entry *gtlbe =
+               get_entry(vcpu_e500, tlbsel, esel);
        struct vcpu_id_table *idt = vcpu_e500->idt;
        unsigned int pr, tid, ts, pid;
        u32 val, eaddr;
@@ -414,25 +432,57 @@ static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
        preempt_enable();
 }
 
+static int tlb0_set_base(gva_t addr, int sets, int ways)
+{
+       int set_base;
+
+       set_base = (addr >> PAGE_SHIFT) & (sets - 1);
+       set_base *= ways;
+
+       return set_base;
+}
+
+static int gtlb0_set_base(struct kvmppc_vcpu_e500 *vcpu_e500, gva_t addr)
+{
+       return tlb0_set_base(addr, vcpu_e500->gtlb_params[0].sets,
+                            vcpu_e500->gtlb_params[0].ways);
+}
+
+static unsigned int get_tlb_esel(struct kvm_vcpu *vcpu, int tlbsel)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+       int esel = get_tlb_esel_bit(vcpu);
+
+       if (tlbsel == 0) {
+               esel &= vcpu_e500->gtlb_params[0].ways - 1;
+               esel += gtlb0_set_base(vcpu_e500, vcpu->arch.shared->mas2);
+       } else {
+               esel &= vcpu_e500->gtlb_params[tlbsel].entries - 1;
+       }
+
+       return esel;
+}
+
 /* Search the guest TLB for a matching entry. */
 static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
                gva_t eaddr, int tlbsel, unsigned int pid, int as)
 {
-       int size = vcpu_e500->gtlb_size[tlbsel];
-       int set_base;
+       int size = vcpu_e500->gtlb_params[tlbsel].entries;
+       unsigned int set_base, offset;
        int i;
 
        if (tlbsel == 0) {
-               int mask = size / KVM_E500_TLB0_WAY_NUM - 1;
-               set_base = (eaddr >> PAGE_SHIFT) & mask;
-               set_base *= KVM_E500_TLB0_WAY_NUM;
-               size = KVM_E500_TLB0_WAY_NUM;
+               set_base = gtlb0_set_base(vcpu_e500, eaddr);
+               size = vcpu_e500->gtlb_params[0].ways;
        } else {
                set_base = 0;
        }
 
+       offset = vcpu_e500->gtlb_offset[tlbsel];
+
        for (i = 0; i < size; i++) {
-               struct tlbe *tlbe = &vcpu_e500->gtlb_arch[tlbsel][set_base + i];
+               struct kvm_book3e_206_tlb_entry *tlbe =
+                       &vcpu_e500->gtlb_arch[offset + set_base + i];
                unsigned int tid;
 
                if (eaddr < get_tlb_eaddr(tlbe))
@@ -457,27 +507,55 @@ static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
        return -1;
 }
 
-static inline void kvmppc_e500_priv_setup(struct tlbe_priv *priv,
-                                         struct tlbe *gtlbe,
-                                         pfn_t pfn)
+static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
+                                        struct kvm_book3e_206_tlb_entry *gtlbe,
+                                        pfn_t pfn)
 {
-       priv->pfn = pfn;
-       priv->flags = E500_TLB_VALID;
+       ref->pfn = pfn;
+       ref->flags = E500_TLB_VALID;
 
        if (tlbe_is_writable(gtlbe))
-               priv->flags |= E500_TLB_DIRTY;
+               ref->flags |= E500_TLB_DIRTY;
 }
 
-static inline void kvmppc_e500_priv_release(struct tlbe_priv *priv)
+static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
-       if (priv->flags & E500_TLB_VALID) {
-               if (priv->flags & E500_TLB_DIRTY)
-                       kvm_release_pfn_dirty(priv->pfn);
+       if (ref->flags & E500_TLB_VALID) {
+               if (ref->flags & E500_TLB_DIRTY)
+                       kvm_release_pfn_dirty(ref->pfn);
                else
-                       kvm_release_pfn_clean(priv->pfn);
+                       kvm_release_pfn_clean(ref->pfn);
+
+               ref->flags = 0;
+       }
+}
+
+static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+       int tlbsel = 0;
+       int i;
+
+       for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
+               struct tlbe_ref *ref =
+                       &vcpu_e500->gtlb_priv[tlbsel][i].ref;
+               kvmppc_e500_ref_release(ref);
+       }
+}
+
+static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+       int stlbsel = 1;
+       int i;
+
+       kvmppc_e500_id_table_reset_all(vcpu_e500);
 
-               priv->flags = 0;
+       for (i = 0; i < host_tlb_params[stlbsel].entries; i++) {
+               struct tlbe_ref *ref =
+                       &vcpu_e500->tlb_refs[stlbsel][i];
+               kvmppc_e500_ref_release(ref);
        }
+
+       clear_tlb_privs(vcpu_e500);
 }
 
 static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
@@ -488,59 +566,54 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
        int tlbsel;
 
        /* since we only have two TLBs, only lower bit is used. */
-       tlbsel = (vcpu_e500->mas4 >> 28) & 0x1;
-       victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0;
-       pidsel = (vcpu_e500->mas4 >> 16) & 0xf;
-       tsized = (vcpu_e500->mas4 >> 7) & 0x1f;
+       tlbsel = (vcpu->arch.shared->mas4 >> 28) & 0x1;
+       victim = (tlbsel == 0) ? gtlb0_get_next_victim(vcpu_e500) : 0;
+       pidsel = (vcpu->arch.shared->mas4 >> 16) & 0xf;
+       tsized = (vcpu->arch.shared->mas4 >> 7) & 0x1f;
 
-       vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
+       vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
                | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-       vcpu_e500->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
+       vcpu->arch.shared->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
                | MAS1_TID(vcpu_e500->pid[pidsel])
                | MAS1_TSIZE(tsized);
-       vcpu_e500->mas2 = (eaddr & MAS2_EPN)
-               | (vcpu_e500->mas4 & MAS2_ATTRIB_MASK);
-       vcpu_e500->mas3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
-       vcpu_e500->mas6 = (vcpu_e500->mas6 & MAS6_SPID1)
+       vcpu->arch.shared->mas2 = (eaddr & MAS2_EPN)
+               | (vcpu->arch.shared->mas4 & MAS2_ATTRIB_MASK);
+       vcpu->arch.shared->mas7_3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
+       vcpu->arch.shared->mas6 = (vcpu->arch.shared->mas6 & MAS6_SPID1)
                | (get_cur_pid(vcpu) << 16)
                | (as ? MAS6_SAS : 0);
-       vcpu_e500->mas7 = 0;
 }
 
-static inline void kvmppc_e500_setup_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
-                                          struct tlbe *gtlbe, int tsize,
-                                          struct tlbe_priv *priv,
-                                          u64 gvaddr, struct tlbe *stlbe)
+/* TID must be supplied by the caller */
+static inline void kvmppc_e500_setup_stlbe(
+       struct kvmppc_vcpu_e500 *vcpu_e500,
+       struct kvm_book3e_206_tlb_entry *gtlbe,
+       int tsize, struct tlbe_ref *ref, u64 gvaddr,
+       struct kvm_book3e_206_tlb_entry *stlbe)
 {
-       pfn_t pfn = priv->pfn;
-       unsigned int stid;
+       pfn_t pfn = ref->pfn;
 
-       stid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe),
-                                  get_tlb_tid(gtlbe),
-                                  get_cur_pr(&vcpu_e500->vcpu), 0);
+       BUG_ON(!(ref->flags & E500_TLB_VALID));
 
        /* Force TS=1 IPROT=0 for all guest mappings. */
-       stlbe->mas1 = MAS1_TSIZE(tsize)
-               | MAS1_TID(stid) | MAS1_TS | MAS1_VALID;
+       stlbe->mas1 = MAS1_TSIZE(tsize) | MAS1_TS | MAS1_VALID;
        stlbe->mas2 = (gvaddr & MAS2_EPN)
                | e500_shadow_mas2_attrib(gtlbe->mas2,
                                vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
-       stlbe->mas3 = ((pfn << PAGE_SHIFT) & MAS3_RPN)
-               | e500_shadow_mas3_attrib(gtlbe->mas3,
+       stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT)
+               | e500_shadow_mas3_attrib(gtlbe->mas7_3,
                                vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
-       stlbe->mas7 = (pfn >> (32 - PAGE_SHIFT)) & MAS7_RPN;
 }
 
-
 static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-       u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel,
-       struct tlbe *stlbe)
+       u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
+       int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe,
+       struct tlbe_ref *ref)
 {
        struct kvm_memory_slot *slot;
        unsigned long pfn, hva;
        int pfnmap = 0;
        int tsize = BOOK3E_PAGESZ_4K;
-       struct tlbe_priv *priv;
 
        /*
         * Translate guest physical to true physical, acquiring
@@ -621,12 +694,31 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
                                pfn &= ~(tsize_pages - 1);
                                break;
                        }
+               } else if (vma && hva >= vma->vm_start &&
+                          (vma->vm_flags & VM_HUGETLB)) {
+                       unsigned long psize = vma_kernel_pagesize(vma);
+
+                       tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >>
+                               MAS1_TSIZE_SHIFT;
+
+                       /*
+                        * Take the largest page size that satisfies both host
+                        * and guest mapping
+                        */
+                       tsize = min(__ilog2(psize) - 10, tsize);
+
+                       /*
+                        * e500 doesn't implement the lowest tsize bit,
+                        * or 1K pages.
+                        */
+                       tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1);
                }
 
                up_read(&current->mm->mmap_sem);
        }
 
        if (likely(!pfnmap)) {
+               unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
                pfn = gfn_to_pfn_memslot(vcpu_e500->vcpu.kvm, slot, gfn);
                if (is_error_pfn(pfn)) {
                        printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
@@ -634,45 +726,52 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
                        kvm_release_pfn_clean(pfn);
                        return;
                }
+
+               /* Align guest and physical address to page map boundaries */
+               pfn &= ~(tsize_pages - 1);
+               gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
        }
 
-       /* Drop old priv and setup new one. */
-       priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
-       kvmppc_e500_priv_release(priv);
-       kvmppc_e500_priv_setup(priv, gtlbe, pfn);
+       /* Drop old ref and setup new one. */
+       kvmppc_e500_ref_release(ref);
+       kvmppc_e500_ref_setup(ref, gtlbe, pfn);
 
-       kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, tsize, priv, gvaddr, stlbe);
+       kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, tsize, ref, gvaddr, stlbe);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
-static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-                               int esel, struct tlbe *stlbe)
+static void kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
+                                int esel,
+                                struct kvm_book3e_206_tlb_entry *stlbe)
 {
-       struct tlbe *gtlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
+       struct tlbe_ref *ref;
 
-       gtlbe = &vcpu_e500->gtlb_arch[0][esel];
+       gtlbe = get_entry(vcpu_e500, 0, esel);
+       ref = &vcpu_e500->gtlb_priv[0][esel].ref;
 
        kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe),
                        get_tlb_raddr(gtlbe) >> PAGE_SHIFT,
-                       gtlbe, 0, esel, stlbe);
-
-       return esel;
+                       gtlbe, 0, stlbe, ref);
 }
 
 /* Caller must ensure that the specified guest TLB entry is safe to insert into
  * the shadow TLB. */
 /* XXX for both one-one and one-to-many , for now use TLB1 */
 static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-               u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, struct tlbe *stlbe)
+               u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
+               struct kvm_book3e_206_tlb_entry *stlbe)
 {
+       struct tlbe_ref *ref;
        unsigned int victim;
 
-       victim = vcpu_e500->gtlb_nv[1]++;
+       victim = vcpu_e500->host_tlb1_nv++;
 
-       if (unlikely(vcpu_e500->gtlb_nv[1] >= tlb1_max_shadow_size()))
-               vcpu_e500->gtlb_nv[1] = 0;
+       if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size()))
+               vcpu_e500->host_tlb1_nv = 0;
 
-       kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim, stlbe);
+       ref = &vcpu_e500->tlb_refs[1][victim];
+       kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe, ref);
 
        return victim;
 }
@@ -689,7 +788,8 @@ static inline int kvmppc_e500_gtlbe_invalidate(
                                struct kvmppc_vcpu_e500 *vcpu_e500,
                                int tlbsel, int esel)
 {
-       struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       struct kvm_book3e_206_tlb_entry *gtlbe =
+               get_entry(vcpu_e500, tlbsel, esel);
 
        if (unlikely(get_tlb_iprot(gtlbe)))
                return -1;
@@ -704,10 +804,10 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
        int esel;
 
        if (value & MMUCSR0_TLB0FI)
-               for (esel = 0; esel < vcpu_e500->gtlb_size[0]; esel++)
+               for (esel = 0; esel < vcpu_e500->gtlb_params[0].entries; esel++)
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, 0, esel);
        if (value & MMUCSR0_TLB1FI)
-               for (esel = 0; esel < vcpu_e500->gtlb_size[1]; esel++)
+               for (esel = 0; esel < vcpu_e500->gtlb_params[1].entries; esel++)
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, 1, esel);
 
        /* Invalidate all vcpu id mappings */
@@ -732,7 +832,8 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 
        if (ia) {
                /* invalidate all entries */
-               for (esel = 0; esel < vcpu_e500->gtlb_size[tlbsel]; esel++)
+               for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries;
+                    esel++)
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
        } else {
                ea &= 0xfffff000;
@@ -752,18 +853,17 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int tlbsel, esel;
-       struct tlbe *gtlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
 
-       tlbsel = get_tlb_tlbsel(vcpu_e500);
-       esel = get_tlb_esel(vcpu_e500, tlbsel);
+       tlbsel = get_tlb_tlbsel(vcpu);
+       esel = get_tlb_esel(vcpu, tlbsel);
 
-       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
-       vcpu_e500->mas0 &= ~MAS0_NV(~0);
-       vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-       vcpu_e500->mas1 = gtlbe->mas1;
-       vcpu_e500->mas2 = gtlbe->mas2;
-       vcpu_e500->mas3 = gtlbe->mas3;
-       vcpu_e500->mas7 = gtlbe->mas7;
+       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
+       vcpu->arch.shared->mas0 &= ~MAS0_NV(~0);
+       vcpu->arch.shared->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
+       vcpu->arch.shared->mas1 = gtlbe->mas1;
+       vcpu->arch.shared->mas2 = gtlbe->mas2;
+       vcpu->arch.shared->mas7_3 = gtlbe->mas7_3;
 
        return EMULATE_DONE;
 }
@@ -771,10 +871,10 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       int as = !!get_cur_sas(vcpu_e500);
-       unsigned int pid = get_cur_spid(vcpu_e500);
+       int as = !!get_cur_sas(vcpu);
+       unsigned int pid = get_cur_spid(vcpu);
        int esel, tlbsel;
-       struct tlbe *gtlbe = NULL;
+       struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
        gva_t ea;
 
        ea = kvmppc_get_gpr(vcpu, rb);
@@ -782,70 +882,90 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
        for (tlbsel = 0; tlbsel < 2; tlbsel++) {
                esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
                if (esel >= 0) {
-                       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+                       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
                        break;
                }
        }
 
        if (gtlbe) {
-               vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
+               esel &= vcpu_e500->gtlb_params[tlbsel].ways - 1;
+
+               vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
                        | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-               vcpu_e500->mas1 = gtlbe->mas1;
-               vcpu_e500->mas2 = gtlbe->mas2;
-               vcpu_e500->mas3 = gtlbe->mas3;
-               vcpu_e500->mas7 = gtlbe->mas7;
+               vcpu->arch.shared->mas1 = gtlbe->mas1;
+               vcpu->arch.shared->mas2 = gtlbe->mas2;
+               vcpu->arch.shared->mas7_3 = gtlbe->mas7_3;
        } else {
                int victim;
 
                /* since we only have two TLBs, only lower bit is used. */
-               tlbsel = vcpu_e500->mas4 >> 28 & 0x1;
-               victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0;
+               tlbsel = vcpu->arch.shared->mas4 >> 28 & 0x1;
+               victim = (tlbsel == 0) ? gtlb0_get_next_victim(vcpu_e500) : 0;
 
-               vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
+               vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel)
+                       | MAS0_ESEL(victim)
                        | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-               vcpu_e500->mas1 = (vcpu_e500->mas6 & MAS6_SPID0)
-                       | (vcpu_e500->mas6 & (MAS6_SAS ? MAS1_TS : 0))
-                       | (vcpu_e500->mas4 & MAS4_TSIZED(~0));
-               vcpu_e500->mas2 &= MAS2_EPN;
-               vcpu_e500->mas2 |= vcpu_e500->mas4 & MAS2_ATTRIB_MASK;
-               vcpu_e500->mas3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
-               vcpu_e500->mas7 = 0;
+               vcpu->arch.shared->mas1 =
+                         (vcpu->arch.shared->mas6 & MAS6_SPID0)
+                       | (vcpu->arch.shared->mas6 & (MAS6_SAS ? MAS1_TS : 0))
+                       | (vcpu->arch.shared->mas4 & MAS4_TSIZED(~0));
+               vcpu->arch.shared->mas2 &= MAS2_EPN;
+               vcpu->arch.shared->mas2 |= vcpu->arch.shared->mas4 &
+                                          MAS2_ATTRIB_MASK;
+               vcpu->arch.shared->mas7_3 &= MAS3_U0 | MAS3_U1 |
+                                            MAS3_U2 | MAS3_U3;
        }
 
        kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
        return EMULATE_DONE;
 }
 
+/* sesel is for tlb1 only */
+static void write_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
+                       struct kvm_book3e_206_tlb_entry *gtlbe,
+                       struct kvm_book3e_206_tlb_entry *stlbe,
+                       int stlbsel, int sesel)
+{
+       int stid;
+
+       preempt_disable();
+       stid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe),
+                                  get_tlb_tid(gtlbe),
+                                  get_cur_pr(&vcpu_e500->vcpu), 0);
+
+       stlbe->mas1 |= MAS1_TID(stid);
+       write_host_tlbe(vcpu_e500, stlbsel, sesel, stlbe);
+       preempt_enable();
+}
+
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe *gtlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
        int tlbsel, esel;
 
-       tlbsel = get_tlb_tlbsel(vcpu_e500);
-       esel = get_tlb_esel(vcpu_e500, tlbsel);
+       tlbsel = get_tlb_tlbsel(vcpu);
+       esel = get_tlb_esel(vcpu, tlbsel);
 
-       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
 
        if (get_tlb_v(gtlbe))
-               kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel);
+               inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
 
-       gtlbe->mas1 = vcpu_e500->mas1;
-       gtlbe->mas2 = vcpu_e500->mas2;
-       gtlbe->mas3 = vcpu_e500->mas3;
-       gtlbe->mas7 = vcpu_e500->mas7;
+       gtlbe->mas1 = vcpu->arch.shared->mas1;
+       gtlbe->mas2 = vcpu->arch.shared->mas2;
+       gtlbe->mas7_3 = vcpu->arch.shared->mas7_3;
 
-       trace_kvm_gtlb_write(vcpu_e500->mas0, gtlbe->mas1, gtlbe->mas2,
-                            gtlbe->mas3, gtlbe->mas7);
+       trace_kvm_booke206_gtlb_write(vcpu->arch.shared->mas0, gtlbe->mas1,
+                                     gtlbe->mas2, gtlbe->mas7_3);
 
        /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
        if (tlbe_is_host_safe(vcpu, gtlbe)) {
-               struct tlbe stlbe;
+               struct kvm_book3e_206_tlb_entry stlbe;
                int stlbsel, sesel;
                u64 eaddr;
                u64 raddr;
 
-               preempt_disable();
                switch (tlbsel) {
                case 0:
                        /* TLB0 */
@@ -853,7 +973,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
                        gtlbe->mas1 |= MAS1_TSIZE(BOOK3E_PAGESZ_4K);
 
                        stlbsel = 0;
-                       sesel = kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+                       kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+                       sesel = 0; /* unused */
 
                        break;
 
@@ -874,8 +995,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
                default:
                        BUG();
                }
-               write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
-               preempt_enable();
+
+               write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
        }
 
        kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
@@ -914,9 +1035,11 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
                        gva_t eaddr)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe *gtlbe =
-               &vcpu_e500->gtlb_arch[tlbsel_of(index)][esel_of(index)];
-       u64 pgmask = get_tlb_bytes(gtlbe) - 1;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
+       u64 pgmask;
+
+       gtlbe = get_entry(vcpu_e500, tlbsel_of(index), esel_of(index));
+       pgmask = get_tlb_bytes(gtlbe) - 1;
 
        return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
 }
@@ -930,22 +1053,21 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        struct tlbe_priv *priv;
-       struct tlbe *gtlbe, stlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe, stlbe;
        int tlbsel = tlbsel_of(index);
        int esel = esel_of(index);
        int stlbsel, sesel;
 
-       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
 
-       preempt_disable();
        switch (tlbsel) {
        case 0:
                stlbsel = 0;
-               sesel = esel;
-               priv = &vcpu_e500->gtlb_priv[stlbsel][sesel];
+               sesel = 0; /* unused */
+               priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
                kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, BOOK3E_PAGESZ_4K,
-                                       priv, eaddr, &stlbe);
+                                       &priv->ref, eaddr, &stlbe);
                break;
 
        case 1: {
@@ -962,8 +1084,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
                break;
        }
 
-       write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
-       preempt_enable();
+       write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
 }
 
 int kvmppc_e500_tlb_search(struct kvm_vcpu *vcpu,
@@ -993,85 +1114,279 @@ void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid)
 
 void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       struct tlbe *tlbe;
+       struct kvm_book3e_206_tlb_entry *tlbe;
 
        /* Insert large initial mapping for guest. */
-       tlbe = &vcpu_e500->gtlb_arch[1][0];
+       tlbe = get_entry(vcpu_e500, 1, 0);
        tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_256M);
        tlbe->mas2 = 0;
-       tlbe->mas3 = E500_TLB_SUPER_PERM_MASK;
-       tlbe->mas7 = 0;
+       tlbe->mas7_3 = E500_TLB_SUPER_PERM_MASK;
 
        /* 4K map for serial output. Used by kernel wrapper. */
-       tlbe = &vcpu_e500->gtlb_arch[1][1];
+       tlbe = get_entry(vcpu_e500, 1, 1);
        tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_4K);
        tlbe->mas2 = (0xe0004500 & 0xFFFFF000) | MAS2_I | MAS2_G;
-       tlbe->mas3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
-       tlbe->mas7 = 0;
+       tlbe->mas7_3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
+}
+
+static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+       int i;
+
+       clear_tlb_refs(vcpu_e500);
+       kfree(vcpu_e500->gtlb_priv[0]);
+       kfree(vcpu_e500->gtlb_priv[1]);
+
+       if (vcpu_e500->shared_tlb_pages) {
+               vfree((void *)(round_down((uintptr_t)vcpu_e500->gtlb_arch,
+                                         PAGE_SIZE)));
+
+               for (i = 0; i < vcpu_e500->num_shared_tlb_pages; i++) {
+                       set_page_dirty_lock(vcpu_e500->shared_tlb_pages[i]);
+                       put_page(vcpu_e500->shared_tlb_pages[i]);
+               }
+
+               vcpu_e500->num_shared_tlb_pages = 0;
+               vcpu_e500->shared_tlb_pages = NULL;
+       } else {
+               kfree(vcpu_e500->gtlb_arch);
+       }
+
+       vcpu_e500->gtlb_arch = NULL;
+}
+
+int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
+                             struct kvm_config_tlb *cfg)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+       struct kvm_book3e_206_tlb_params params;
+       char *virt;
+       struct page **pages;
+       struct tlbe_priv *privs[2] = {};
+       size_t array_len;
+       u32 sets;
+       int num_pages, ret, i;
+
+       if (cfg->mmu_type != KVM_MMU_FSL_BOOKE_NOHV)
+               return -EINVAL;
+
+       if (copy_from_user(&params, (void __user *)(uintptr_t)cfg->params,
+                          sizeof(params)))
+               return -EFAULT;
+
+       if (params.tlb_sizes[1] > 64)
+               return -EINVAL;
+       if (params.tlb_ways[1] != params.tlb_sizes[1])
+               return -EINVAL;
+       if (params.tlb_sizes[2] != 0 || params.tlb_sizes[3] != 0)
+               return -EINVAL;
+       if (params.tlb_ways[2] != 0 || params.tlb_ways[3] != 0)
+               return -EINVAL;
+
+       if (!is_power_of_2(params.tlb_ways[0]))
+               return -EINVAL;
+
+       sets = params.tlb_sizes[0] >> ilog2(params.tlb_ways[0]);
+       if (!is_power_of_2(sets))
+               return -EINVAL;
+
+       array_len = params.tlb_sizes[0] + params.tlb_sizes[1];
+       array_len *= sizeof(struct kvm_book3e_206_tlb_entry);
+
+       if (cfg->array_len < array_len)
+               return -EINVAL;
+
+       num_pages = DIV_ROUND_UP(cfg->array + array_len - 1, PAGE_SIZE) -
+                   cfg->array / PAGE_SIZE;
+       pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
+       if (!pages)
+               return -ENOMEM;
+
+       ret = get_user_pages_fast(cfg->array, num_pages, 1, pages);
+       if (ret < 0)
+               goto err_pages;
+
+       if (ret != num_pages) {
+               num_pages = ret;
+               ret = -EFAULT;
+               goto err_put_page;
+       }
+
+       virt = vmap(pages, num_pages, VM_MAP, PAGE_KERNEL);
+       if (!virt)
+               goto err_put_page;
+
+       privs[0] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[0],
+                          GFP_KERNEL);
+       privs[1] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[1],
+                          GFP_KERNEL);
+
+       if (!privs[0] || !privs[1])
+               goto err_put_page;
+
+       free_gtlb(vcpu_e500);
+
+       vcpu_e500->gtlb_priv[0] = privs[0];
+       vcpu_e500->gtlb_priv[1] = privs[1];
+
+       vcpu_e500->gtlb_arch = (struct kvm_book3e_206_tlb_entry *)
+               (virt + (cfg->array & (PAGE_SIZE - 1)));
+
+       vcpu_e500->gtlb_params[0].entries = params.tlb_sizes[0];
+       vcpu_e500->gtlb_params[1].entries = params.tlb_sizes[1];
+
+       vcpu_e500->gtlb_offset[0] = 0;
+       vcpu_e500->gtlb_offset[1] = params.tlb_sizes[0];
+
+       vcpu_e500->tlb0cfg &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       if (params.tlb_sizes[0] <= 2048)
+               vcpu_e500->tlb0cfg |= params.tlb_sizes[0];
+       vcpu_e500->tlb0cfg |= params.tlb_ways[0] << TLBnCFG_ASSOC_SHIFT;
+
+       vcpu_e500->tlb1cfg &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       vcpu_e500->tlb1cfg |= params.tlb_sizes[1];
+       vcpu_e500->tlb1cfg |= params.tlb_ways[1] << TLBnCFG_ASSOC_SHIFT;
+
+       vcpu_e500->shared_tlb_pages = pages;
+       vcpu_e500->num_shared_tlb_pages = num_pages;
+
+       vcpu_e500->gtlb_params[0].ways = params.tlb_ways[0];
+       vcpu_e500->gtlb_params[0].sets = sets;
+
+       vcpu_e500->gtlb_params[1].ways = params.tlb_sizes[1];
+       vcpu_e500->gtlb_params[1].sets = 1;
+
+       return 0;
+
+err_put_page:
+       kfree(privs[0]);
+       kfree(privs[1]);
+
+       for (i = 0; i < num_pages; i++)
+               put_page(pages[i]);
+
+err_pages:
+       kfree(pages);
+       return ret;
+}
+
+int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
+                            struct kvm_dirty_tlb *dirty)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+
+       clear_tlb_refs(vcpu_e500);
+       return 0;
 }
 
 int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       tlb1_entry_num = mfspr(SPRN_TLB1CFG) & 0xFFF;
-
-       vcpu_e500->gtlb_size[0] = KVM_E500_TLB0_SIZE;
-       vcpu_e500->gtlb_arch[0] =
-               kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-       if (vcpu_e500->gtlb_arch[0] == NULL)
-               goto err_out;
-
-       vcpu_e500->gtlb_size[1] = KVM_E500_TLB1_SIZE;
-       vcpu_e500->gtlb_arch[1] =
-               kzalloc(sizeof(struct tlbe) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
-       if (vcpu_e500->gtlb_arch[1] == NULL)
-               goto err_out_guest0;
-
-       vcpu_e500->gtlb_priv[0] = (struct tlbe_priv *)
-               kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-       if (vcpu_e500->gtlb_priv[0] == NULL)
-               goto err_out_guest1;
-       vcpu_e500->gtlb_priv[1] = (struct tlbe_priv *)
-               kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
-
-       if (vcpu_e500->gtlb_priv[1] == NULL)
-               goto err_out_priv0;
+       int entry_size = sizeof(struct kvm_book3e_206_tlb_entry);
+       int entries = KVM_E500_TLB0_SIZE + KVM_E500_TLB1_SIZE;
+
+       host_tlb_params[0].entries = mfspr(SPRN_TLB0CFG) & TLBnCFG_N_ENTRY;
+       host_tlb_params[1].entries = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+       /*
+        * This should never happen on real e500 hardware, but is
+        * architecturally possible -- e.g. in some weird nested
+        * virtualization case.
+        */
+       if (host_tlb_params[0].entries == 0 ||
+           host_tlb_params[1].entries == 0) {
+               pr_err("%s: need to know host tlb size\n", __func__);
+               return -ENODEV;
+       }
+
+       host_tlb_params[0].ways = (mfspr(SPRN_TLB0CFG) & TLBnCFG_ASSOC) >>
+                                 TLBnCFG_ASSOC_SHIFT;
+       host_tlb_params[1].ways = host_tlb_params[1].entries;
+
+       if (!is_power_of_2(host_tlb_params[0].entries) ||
+           !is_power_of_2(host_tlb_params[0].ways) ||
+           host_tlb_params[0].entries < host_tlb_params[0].ways ||
+           host_tlb_params[0].ways == 0) {
+               pr_err("%s: bad tlb0 host config: %u entries %u ways\n",
+                      __func__, host_tlb_params[0].entries,
+                      host_tlb_params[0].ways);
+               return -ENODEV;
+       }
+
+       host_tlb_params[0].sets =
+               host_tlb_params[0].entries / host_tlb_params[0].ways;
+       host_tlb_params[1].sets = 1;
+
+       vcpu_e500->gtlb_params[0].entries = KVM_E500_TLB0_SIZE;
+       vcpu_e500->gtlb_params[1].entries = KVM_E500_TLB1_SIZE;
+
+       vcpu_e500->gtlb_params[0].ways = KVM_E500_TLB0_WAY_NUM;
+       vcpu_e500->gtlb_params[0].sets =
+               KVM_E500_TLB0_SIZE / KVM_E500_TLB0_WAY_NUM;
+
+       vcpu_e500->gtlb_params[1].ways = KVM_E500_TLB1_SIZE;
+       vcpu_e500->gtlb_params[1].sets = 1;
+
+       vcpu_e500->gtlb_arch = kmalloc(entries * entry_size, GFP_KERNEL);
+       if (!vcpu_e500->gtlb_arch)
+               return -ENOMEM;
+
+       vcpu_e500->gtlb_offset[0] = 0;
+       vcpu_e500->gtlb_offset[1] = KVM_E500_TLB0_SIZE;
+
+       vcpu_e500->tlb_refs[0] =
+               kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[0].entries,
+                       GFP_KERNEL);
+       if (!vcpu_e500->tlb_refs[0])
+               goto err;
+
+       vcpu_e500->tlb_refs[1] =
+               kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[1].entries,
+                       GFP_KERNEL);
+       if (!vcpu_e500->tlb_refs[1])
+               goto err;
+
+       vcpu_e500->gtlb_priv[0] = kzalloc(sizeof(struct tlbe_ref) *
+                                         vcpu_e500->gtlb_params[0].entries,
+                                         GFP_KERNEL);
+       if (!vcpu_e500->gtlb_priv[0])
+               goto err;
+
+       vcpu_e500->gtlb_priv[1] = kzalloc(sizeof(struct tlbe_ref) *
+                                         vcpu_e500->gtlb_params[1].entries,
+                                         GFP_KERNEL);
+       if (!vcpu_e500->gtlb_priv[1])
+               goto err;
 
        if (kvmppc_e500_id_table_alloc(vcpu_e500) == NULL)
-               goto err_out_priv1;
+               goto err;
 
        /* Init TLB configuration register */
-       vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) & ~0xfffUL;
-       vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_size[0];
-       vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) & ~0xfffUL;
-       vcpu_e500->tlb1cfg |= vcpu_e500->gtlb_size[1];
+       vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) &
+                            ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_params[0].entries;
+       vcpu_e500->tlb0cfg |=
+               vcpu_e500->gtlb_params[0].ways << TLBnCFG_ASSOC_SHIFT;
+
+       vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) &
+                            ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_params[1].entries;
+       vcpu_e500->tlb0cfg |=
+               vcpu_e500->gtlb_params[1].ways << TLBnCFG_ASSOC_SHIFT;
 
        return 0;
 
-err_out_priv1:
-       kfree(vcpu_e500->gtlb_priv[1]);
-err_out_priv0:
-       kfree(vcpu_e500->gtlb_priv[0]);
-err_out_guest1:
-       kfree(vcpu_e500->gtlb_arch[1]);
-err_out_guest0:
-       kfree(vcpu_e500->gtlb_arch[0]);
-err_out:
+err:
+       free_gtlb(vcpu_e500);
+       kfree(vcpu_e500->tlb_refs[0]);
+       kfree(vcpu_e500->tlb_refs[1]);
        return -1;
 }
 
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       int stlbsel, i;
-
-       /* release all privs */
-       for (stlbsel = 0; stlbsel < 2; stlbsel++)
-               for (i = 0; i < vcpu_e500->gtlb_size[stlbsel]; i++) {
-                       struct tlbe_priv *priv =
-                               &vcpu_e500->gtlb_priv[stlbsel][i];
-                       kvmppc_e500_priv_release(priv);
-               }
-
+       free_gtlb(vcpu_e500);
        kvmppc_e500_id_table_free(vcpu_e500);
-       kfree(vcpu_e500->gtlb_arch[1]);
-       kfree(vcpu_e500->gtlb_arch[0]);
+
+       kfree(vcpu_e500->tlb_refs[0]);
+       kfree(vcpu_e500->tlb_refs[1]);
 }
index 59b88e99a235612126a4781671edaccf6e1f0c14..5c6d2d7bf058f8efd657c6f8dea558ba3500f44b 100644 (file)
 #include <asm/tlb.h>
 #include <asm/kvm_e500.h>
 
-#define KVM_E500_TLB0_WAY_SIZE_BIT     7       /* Fixed */
-#define KVM_E500_TLB0_WAY_SIZE         (1UL << KVM_E500_TLB0_WAY_SIZE_BIT)
-#define KVM_E500_TLB0_WAY_SIZE_MASK    (KVM_E500_TLB0_WAY_SIZE - 1)
-
-#define KVM_E500_TLB0_WAY_NUM_BIT      1       /* No greater than 7 */
-#define KVM_E500_TLB0_WAY_NUM          (1UL << KVM_E500_TLB0_WAY_NUM_BIT)
-#define KVM_E500_TLB0_WAY_NUM_MASK     (KVM_E500_TLB0_WAY_NUM - 1)
+/* This geometry is the legacy default -- can be overridden by userspace */
+#define KVM_E500_TLB0_WAY_SIZE         128
+#define KVM_E500_TLB0_WAY_NUM          2
 
 #define KVM_E500_TLB0_SIZE  (KVM_E500_TLB0_WAY_SIZE * KVM_E500_TLB0_WAY_NUM)
 #define KVM_E500_TLB1_SIZE  16
@@ -58,50 +54,54 @@ extern void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *);
 extern void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *);
 
 /* TLB helper functions */
-static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_size(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 7) & 0x1f;
 }
 
-static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe)
+static inline gva_t get_tlb_eaddr(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return tlbe->mas2 & 0xfffff000;
 }
 
-static inline u64 get_tlb_bytes(const struct tlbe *tlbe)
+static inline u64 get_tlb_bytes(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        unsigned int pgsize = get_tlb_size(tlbe);
        return 1ULL << 10 << pgsize;
 }
 
-static inline gva_t get_tlb_end(const struct tlbe *tlbe)
+static inline gva_t get_tlb_end(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        u64 bytes = get_tlb_bytes(tlbe);
        return get_tlb_eaddr(tlbe) + bytes - 1;
 }
 
-static inline u64 get_tlb_raddr(const struct tlbe *tlbe)
+static inline u64 get_tlb_raddr(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
-       u64 rpn = tlbe->mas7;
-       return (rpn << 32) | (tlbe->mas3 & 0xfffff000);
+       return tlbe->mas7_3 & ~0xfffULL;
 }
 
-static inline unsigned int get_tlb_tid(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_tid(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 16) & 0xff;
 }
 
-static inline unsigned int get_tlb_ts(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_ts(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 12) & 0x1;
 }
 
-static inline unsigned int get_tlb_v(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_v(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 31) & 0x1;
 }
 
-static inline unsigned int get_tlb_iprot(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_iprot(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 30) & 0x1;
 }
@@ -121,59 +121,37 @@ static inline unsigned int get_cur_pr(struct kvm_vcpu *vcpu)
        return !!(vcpu->arch.shared->msr & MSR_PR);
 }
 
-static inline unsigned int get_cur_spid(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_cur_spid(const struct kvm_vcpu *vcpu)
 {
-       return (vcpu_e500->mas6 >> 16) & 0xff;
+       return (vcpu->arch.shared->mas6 >> 16) & 0xff;
 }
 
-static inline unsigned int get_cur_sas(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_cur_sas(const struct kvm_vcpu *vcpu)
 {
-       return vcpu_e500->mas6 & 0x1;
+       return vcpu->arch.shared->mas6 & 0x1;
 }
 
-static inline unsigned int get_tlb_tlbsel(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_tlb_tlbsel(const struct kvm_vcpu *vcpu)
 {
        /*
         * Manual says that tlbsel has 2 bits wide.
         * Since we only have two TLBs, only lower bit is used.
         */
-       return (vcpu_e500->mas0 >> 28) & 0x1;
-}
-
-static inline unsigned int get_tlb_nv_bit(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
-{
-       return vcpu_e500->mas0 & 0xfff;
+       return (vcpu->arch.shared->mas0 >> 28) & 0x1;
 }
 
-static inline unsigned int get_tlb_esel_bit(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_tlb_nv_bit(const struct kvm_vcpu *vcpu)
 {
-       return (vcpu_e500->mas0 >> 16) & 0xfff;
+       return vcpu->arch.shared->mas0 & 0xfff;
 }
 
-static inline unsigned int get_tlb_esel(
-               const struct kvmppc_vcpu_e500 *vcpu_e500,
-               int tlbsel)
+static inline unsigned int get_tlb_esel_bit(const struct kvm_vcpu *vcpu)
 {
-       unsigned int esel = get_tlb_esel_bit(vcpu_e500);
-
-       if (tlbsel == 0) {
-               esel &= KVM_E500_TLB0_WAY_NUM_MASK;
-               esel |= ((vcpu_e500->mas2 >> 12) & KVM_E500_TLB0_WAY_SIZE_MASK)
-                               << KVM_E500_TLB0_WAY_NUM_BIT;
-       } else {
-               esel &= KVM_E500_TLB1_SIZE - 1;
-       }
-
-       return esel;
+       return (vcpu->arch.shared->mas0 >> 16) & 0xfff;
 }
 
 static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
-                       const struct tlbe *tlbe)
+                       const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        gpa_t gpa;
 
index 141dce3c6810839b65f519767c070d28c3c11fa0..968f401018834aa4758ec45afeb32eee327a37c8 100644 (file)
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright IBM Corp. 2007
+ * Copyright 2011 Freescale Semiconductor, Inc.
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
 #define OP_STH  44
 #define OP_STHU 45
 
-#ifdef CONFIG_PPC_BOOK3S
-static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
-{
-       return 1;
-}
-#else
-static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.tcr & TCR_DIE;
-}
-#endif
-
 void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
 {
        unsigned long dec_nsec;
+       unsigned long long dec_time;
 
        pr_debug("mtDEC: %x\n", vcpu->arch.dec);
+       hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+
 #ifdef CONFIG_PPC_BOOK3S
        /* mtdec lowers the interrupt line when positive. */
        kvmppc_core_dequeue_dec(vcpu);
 
        /* POWER4+ triggers a dec interrupt if the value is < 0 */
        if (vcpu->arch.dec & 0x80000000) {
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
                kvmppc_core_queue_dec(vcpu);
                return;
        }
 #endif
-       if (kvmppc_dec_enabled(vcpu)) {
-               /* The decrementer ticks at the same rate as the timebase, so
-                * that's how we convert the guest DEC value to the number of
-                * host ticks. */
-
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-               dec_nsec = vcpu->arch.dec;
-               dec_nsec *= 1000;
-               dec_nsec /= tb_ticks_per_usec;
-               hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
-                             HRTIMER_MODE_REL);
-               vcpu->arch.dec_jiffies = get_tb();
-       } else {
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-       }
+
+#ifdef CONFIG_BOOKE
+       /* On BOOKE, DEC = 0 is as good as decrementer not enabled */
+       if (vcpu->arch.dec == 0)
+               return;
+#endif
+
+       /*
+        * The decrementer ticks at the same rate as the timebase, so
+        * that's how we convert the guest DEC value to the number of
+        * host ticks.
+        */
+
+       dec_time = vcpu->arch.dec;
+       dec_time *= 1000;
+       do_div(dec_time, tb_ticks_per_usec);
+       dec_nsec = do_div(dec_time, NSEC_PER_SEC);
+       hrtimer_start(&vcpu->arch.dec_timer,
+               ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL);
+       vcpu->arch.dec_jiffies = get_tb();
 }
 
 u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
 {
        u64 jd = tb - vcpu->arch.dec_jiffies;
+
+#ifdef CONFIG_BOOKE
+       if (vcpu->arch.dec < jd)
+               return 0;
+#endif
+
        return vcpu->arch.dec - jd;
 }
 
@@ -159,7 +161,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
        case OP_TRAP_64:
                kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
 #else
-               kvmppc_core_queue_program(vcpu, vcpu->arch.esr | ESR_PTR);
+               kvmppc_core_queue_program(vcpu,
+                                         vcpu->arch.shared->esr | ESR_PTR);
 #endif
                advance = 0;
                break;
index 607fbdf24b8484c173cc03593ffc71d968b689fe..00d7e345b3fefef2280fd145d6233bd9acca9719 100644 (file)
@@ -39,7 +39,8 @@
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
        return !(v->arch.shared->msr & MSR_WE) ||
-              !!(v->arch.pending_exceptions);
+              !!(v->arch.pending_exceptions) ||
+              v->requests;
 }
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
@@ -66,7 +67,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
                vcpu->arch.magic_page_pa = param1;
                vcpu->arch.magic_page_ea = param2;
 
-               r2 = KVM_MAGIC_FEAT_SR;
+               r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
                r = HC_EV_SUCCESS;
                break;
@@ -171,8 +172,11 @@ void kvm_arch_check_processor_compat(void *rtn)
        *(int *)rtn = kvmppc_core_check_processor_compat();
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
+       if (type)
+               return -EINVAL;
+
        return kvmppc_core_init_vm(kvm);
 }
 
@@ -208,17 +212,22 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_PPC_BOOKE_SREGS:
 #else
        case KVM_CAP_PPC_SEGSTATE:
+       case KVM_CAP_PPC_HIOR:
        case KVM_CAP_PPC_PAPR:
 #endif
        case KVM_CAP_PPC_UNSET_IRQ:
        case KVM_CAP_PPC_IRQ_LEVEL:
        case KVM_CAP_ENABLE_CAP:
+       case KVM_CAP_ONE_REG:
                r = 1;
                break;
 #ifndef CONFIG_KVM_BOOK3S_64_HV
        case KVM_CAP_PPC_PAIRED_SINGLES:
        case KVM_CAP_PPC_OSI:
        case KVM_CAP_PPC_GET_PVINFO:
+#ifdef CONFIG_KVM_E500
+       case KVM_CAP_SW_TLB:
+#endif
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -238,7 +247,26 @@ int kvm_dev_ioctl_check_extension(long ext)
                if (cpu_has_feature(CPU_FTR_ARCH_201))
                        r = 2;
                break;
+       case KVM_CAP_SYNC_MMU:
+               r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+               break;
 #endif
+       case KVM_CAP_NR_VCPUS:
+               /*
+                * Recommending a number of CPUs is somewhat arbitrary; we
+                * return the number of present CPUs for -HV (since a host
+                * will have secondary threads "offline"), and for other KVM
+                * implementations just count online CPUs.
+                */
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+               r = num_present_cpus();
+#else
+               r = num_online_cpus();
+#endif
+               break;
+       case KVM_CAP_MAX_VCPUS:
+               r = KVM_MAX_VCPUS;
+               break;
        default:
                r = 0;
                break;
@@ -253,6 +281,16 @@ long kvm_arch_dev_ioctl(struct file *filp,
        return -EINVAL;
 }
 
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_memory_slot *memslot,
                                    struct kvm_memory_slot old,
@@ -279,9 +317,10 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        struct kvm_vcpu *vcpu;
        vcpu = kvmppc_core_vcpu_create(kvm, id);
-       vcpu->arch.wqp = &vcpu->wq;
-       if (!IS_ERR(vcpu))
+       if (!IS_ERR(vcpu)) {
+               vcpu->arch.wqp = &vcpu->wq;
                kvmppc_create_vcpu_debugfs(vcpu, id);
+       }
        return vcpu;
 }
 
@@ -305,18 +344,6 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
        return kvmppc_core_pending_dec(vcpu);
 }
 
-static void kvmppc_decrementer_func(unsigned long data)
-{
-       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
-
-       kvmppc_core_queue_dec(vcpu);
-
-       if (waitqueue_active(vcpu->arch.wqp)) {
-               wake_up_interruptible(vcpu->arch.wqp);
-               vcpu->stat.halt_wakeup++;
-       }
-}
-
 /*
  * low level hrtimer wake routine. Because this runs in hardirq context
  * we schedule a tasklet to do the real work.
@@ -431,20 +458,20 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
 
        kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
 
-       switch (vcpu->arch.io_gpr & KVM_REG_EXT_MASK) {
-       case KVM_REG_GPR:
+       switch (vcpu->arch.io_gpr & KVM_MMIO_REG_EXT_MASK) {
+       case KVM_MMIO_REG_GPR:
                kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
                break;
-       case KVM_REG_FPR:
-               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+       case KVM_MMIO_REG_FPR:
+               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
                break;
 #ifdef CONFIG_PPC_BOOK3S
-       case KVM_REG_QPR:
-               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+       case KVM_MMIO_REG_QPR:
+               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
                break;
-       case KVM_REG_FQPR:
-               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
-               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+       case KVM_MMIO_REG_FQPR:
+               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
+               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
                break;
 #endif
        default:
@@ -553,8 +580,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                vcpu->arch.hcall_needed = 0;
        }
 
-       kvmppc_core_deliver_interrupts(vcpu);
-
        r = kvmppc_vcpu_run(run, vcpu);
 
        if (vcpu->sigset_active)
@@ -563,6 +588,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
        return r;
 }
 
+void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
+{
+       int me;
+       int cpu = vcpu->cpu;
+
+       me = get_cpu();
+       if (waitqueue_active(vcpu->arch.wqp)) {
+               wake_up_interruptible(vcpu->arch.wqp);
+               vcpu->stat.halt_wakeup++;
+       } else if (cpu != me && cpu != -1) {
+               smp_send_reschedule(vcpu->cpu);
+       }
+       put_cpu();
+}
+
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 {
        if (irq->irq == KVM_INTERRUPT_UNSET) {
@@ -571,13 +611,7 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
        }
 
        kvmppc_core_queue_external(vcpu, irq);
-
-       if (waitqueue_active(vcpu->arch.wqp)) {
-               wake_up_interruptible(vcpu->arch.wqp);
-               vcpu->stat.halt_wakeup++;
-       } else if (vcpu->cpu != -1) {
-               smp_send_reschedule(vcpu->cpu);
-       }
+       kvm_vcpu_kick(vcpu);
 
        return 0;
 }
@@ -599,6 +633,19 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
                r = 0;
                vcpu->arch.papr_enabled = true;
                break;
+#ifdef CONFIG_KVM_E500
+       case KVM_CAP_SW_TLB: {
+               struct kvm_config_tlb cfg;
+               void __user *user_ptr = (void __user *)(uintptr_t)cap->args[0];
+
+               r = -EFAULT;
+               if (copy_from_user(&cfg, user_ptr, sizeof(cfg)))
+                       break;
+
+               r = kvm_vcpu_ioctl_config_tlb(vcpu, &cfg);
+               break;
+       }
+#endif
        default:
                r = -EINVAL;
                break;
@@ -648,6 +695,32 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
                break;
        }
+
+       case KVM_SET_ONE_REG:
+       case KVM_GET_ONE_REG:
+       {
+               struct kvm_one_reg reg;
+               r = -EFAULT;
+               if (copy_from_user(&reg, argp, sizeof(reg)))
+                       goto out;
+               if (ioctl == KVM_SET_ONE_REG)
+                       r = kvm_vcpu_ioctl_set_one_reg(vcpu, &reg);
+               else
+                       r = kvm_vcpu_ioctl_get_one_reg(vcpu, &reg);
+               break;
+       }
+
+#ifdef CONFIG_KVM_E500
+       case KVM_DIRTY_TLB: {
+               struct kvm_dirty_tlb dirty;
+               r = -EFAULT;
+               if (copy_from_user(&dirty, argp, sizeof(dirty)))
+                       goto out;
+               r = kvm_vcpu_ioctl_dirty_tlb(vcpu, &dirty);
+               break;
+       }
+#endif
+
        default:
                r = -EINVAL;
        }
@@ -656,6 +729,11 @@ out:
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
        u32 inst_lis = 0x3c000000;
index b135d3d397db9630f1a4c7579ee0f1e4a3340a00..877186b7b1c360c5deae3905b076166f6843e21c 100644 (file)
@@ -118,11 +118,14 @@ TRACE_EVENT(kvm_book3s_exit,
        ),
 
        TP_fast_assign(
+               struct kvmppc_book3s_shadow_vcpu *svcpu;
                __entry->exit_nr        = exit_nr;
                __entry->pc             = kvmppc_get_pc(vcpu);
                __entry->dar            = kvmppc_get_fault_dar(vcpu);
                __entry->msr            = vcpu->arch.shared->msr;
-               __entry->srr1           = to_svcpu(vcpu)->shadow_srr1;
+               svcpu = svcpu_get(vcpu);
+               __entry->srr1           = svcpu->shadow_srr1;
+               svcpu_put(svcpu);
        ),
 
        TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx",
@@ -337,6 +340,63 @@ TRACE_EVENT(kvm_book3s_slbmte,
 
 #endif /* CONFIG_PPC_BOOK3S */
 
+
+/*************************************************************************
+ *                         Book3E trace points                           *
+ *************************************************************************/
+
+#ifdef CONFIG_BOOKE
+
+TRACE_EVENT(kvm_booke206_stlb_write,
+       TP_PROTO(__u32 mas0, __u32 mas8, __u32 mas1, __u64 mas2, __u64 mas7_3),
+       TP_ARGS(mas0, mas8, mas1, mas2, mas7_3),
+
+       TP_STRUCT__entry(
+               __field(        __u32,  mas0            )
+               __field(        __u32,  mas8            )
+               __field(        __u32,  mas1            )
+               __field(        __u64,  mas2            )
+               __field(        __u64,  mas7_3          )
+       ),
+
+       TP_fast_assign(
+               __entry->mas0           = mas0;
+               __entry->mas8           = mas8;
+               __entry->mas1           = mas1;
+               __entry->mas2           = mas2;
+               __entry->mas7_3         = mas7_3;
+       ),
+
+       TP_printk("mas0=%x mas8=%x mas1=%x mas2=%llx mas7_3=%llx",
+               __entry->mas0, __entry->mas8, __entry->mas1,
+               __entry->mas2, __entry->mas7_3)
+);
+
+TRACE_EVENT(kvm_booke206_gtlb_write,
+       TP_PROTO(__u32 mas0, __u32 mas1, __u64 mas2, __u64 mas7_3),
+       TP_ARGS(mas0, mas1, mas2, mas7_3),
+
+       TP_STRUCT__entry(
+               __field(        __u32,  mas0            )
+               __field(        __u32,  mas1            )
+               __field(        __u64,  mas2            )
+               __field(        __u64,  mas7_3          )
+       ),
+
+       TP_fast_assign(
+               __entry->mas0           = mas0;
+               __entry->mas1           = mas1;
+               __entry->mas2           = mas2;
+               __entry->mas7_3         = mas7_3;
+       ),
+
+       TP_printk("mas0=%x mas1=%x mas2=%llx mas7_3=%llx",
+               __entry->mas0, __entry->mas1,
+               __entry->mas2, __entry->mas7_3)
+);
+
+#endif
+
 #endif /* _TRACE_KVM_H */
 
 /* This part must be outside protection */
index 13b676c20d126396cf9db44dbbfd1a3238a7b84b..da22c84a8fed6c13421740ce02199560f3896a70 100644 (file)
@@ -3,8 +3,8 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <linux/string.h>
+#include <asm/setup.h>
 
-#include <asm/system.h>
 
 void * __init_refok zalloc_maybe_bootmem(size_t size, gfp_t mask)
 {
index 6e1efadac48b8753b3be3fb3d1e5c9e1b1498a12..bf2654f2b68e7dff11c6fb5f11a7063f1f8aa6dd 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
+#include <asm/switch_to.h>
 
 int enter_vmx_copy(void)
 {
index 388b95e1a00956adead4fe85d382a7f20ca5b3f9..2c9441ee6bb853c4ca6d650bb399c94b5ee5db15 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/memblock.h>
 
 #include <asm/mmu.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
index 19f2f9498b27f9ebc8f746c8e7d7fce42ddab728..08ffcf52a8564211d609bc2cf1fa8dfc3a6e8678 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/siginfo.h>
+#include <asm/debug.h>
 #include <mm/mmu_decl.h>
 
 #include "icswx.h"
index 3e8c37a4e395cc730418eafc12bdd81cb5f0caad..377e5cbedbbb8c962d7d5f9b0fae7473b22b1481 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/mmu_context.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
index 57c7465e656ef6df6e33e125b5ac3479703cce84..fb05b123218f389eaea96a9022d5b39f8cd18188 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/export.h>
 #include <linux/of_fdt.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>
@@ -103,6 +104,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
                *shift = hugepd_shift(*hpdp);
        return hugepte_offset(hpdp, ea, pdshift);
 }
+EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte);
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
@@ -310,7 +312,8 @@ void __init reserve_hugetlb_gpages(void)
        int i;
 
        strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
-       parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup);
+       parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0,
+                       &do_gpage_early_setup);
 
        /*
         * Walk gpage list in reverse, allocating larger page sizes first.
index 6157be2a7049678005df009a578add08be0827ab..01e2db97a210019df0e8b3988585baa670ab1edf 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/btext.h>
 #include <asm/tlb.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
index e94b57fb79a09be65781fbefe4d3e46d194d9f2a..620b7acd2fdfed444e71abf3f080c709482e95d1 100644 (file)
@@ -61,7 +61,6 @@
 #include <asm/mmzone.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 #include <asm/vdso.h>
index 3feefc3842a85471ae33c03307d4ad2907894856..b6edbb3b4a54f96aa46a58e603d927c874806449 100644 (file)
 #include <linux/node.h>
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/paca.h>
 #include <asm/hvcall.h>
+#include <asm/setup.h>
 
 static int numa_enabled = 1;
 
index 0907f92ce309258beb1cd964018b94a9146e2cec..6c856fb8c15b01705fb6cf5ff28c0a232d85d3bd 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 #include "mmu_decl.h"
 
index ad36ede469cc6a1248d520bd6b6915b9b8895501..249a0631c4dbc63ca8cdf0ca422b8663b9a6299f 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
index 6f01624f317f6381f4431a2f4ef81d8c81d0e22c..4f51025f5b00f357ec799c795d889c3e48d851e5 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/pmc.h>
 #include <asm/cputable.h>
 #include <asm/oprofile_impl.h>
index f8d36f940e88697c698b02f089d4a0d9c0f98670..ff617246d128b7a9c5555c42f2b22f4bf9cfa000 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/page.h>
index cb515cff745c91e586875e631450f4432ca84185..b9589c19ccdabff66348caae82bf49ec2ed1d243 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/ptrace.h>
 #include <asm/reg.h>
 #include <asm/rtas.h>
-#include <asm/system.h>
 #include <asm/cell-regs.h>
 
 #include "../platforms/cell/interrupt.h"
index d4e6507277b5ea6ee43dbc1110027f2c4534eef4..ccc1daa33aed9c9d5f3b32a82e369da970769e73 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/reg_fsl_emb.h>
index e6bec74be131246b5ee3d1bce119d9a01c97f51d..95ae77dec3f6ada8e2fc6fc58a223ed235d0032a 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/smp.h>
 #include <asm/firmware.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/rtas.h>
index a20afe45d936639fc2061a02b948e016cae8ba92..9b801b8c8c5adb63c8b9bc908c700ad214411c65 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/oprofile_impl.h>
index c2e27ede07ec8afb138fbaac31b736ea96b6ddc1..02aee03e713c6f287721faa7079ac760c865f7c9 100644 (file)
@@ -116,14 +116,45 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
                *addrp = mfspr(SPRN_SDAR);
 }
 
+static inline u32 perf_flags_from_msr(struct pt_regs *regs)
+{
+       if (regs->msr & MSR_PR)
+               return PERF_RECORD_MISC_USER;
+       if ((regs->msr & MSR_HV) && freeze_events_kernel != MMCR0_FCHV)
+               return PERF_RECORD_MISC_HYPERVISOR;
+       return PERF_RECORD_MISC_KERNEL;
+}
+
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
        unsigned long mmcra = regs->dsisr;
        unsigned long sihv = MMCRA_SIHV;
        unsigned long sipr = MMCRA_SIPR;
 
+       /* Not a PMU interrupt: Make up flags from regs->msr */
        if (TRAP(regs) != 0xf00)
-               return 0;       /* not a PMU interrupt */
+               return perf_flags_from_msr(regs);
+
+       /*
+        * If we don't support continuous sampling and this
+        * is not a marked event, same deal
+        */
+       if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
+           !(mmcra & MMCRA_SAMPLE_ENABLE))
+               return perf_flags_from_msr(regs);
+
+       /*
+        * If we don't have flags in MMCRA, rather than using
+        * the MSR, we intuit the flags from the address in
+        * SIAR which should give slightly more reliable
+        * results
+        */
+       if (ppmu->flags & PPMU_NO_SIPR) {
+               unsigned long siar = mfspr(SPRN_SIAR);
+               if (siar >= PAGE_OFFSET)
+                       return PERF_RECORD_MISC_KERNEL;
+               return PERF_RECORD_MISC_USER;
+       }
 
        if (ppmu->flags & PPMU_ALT_SIPR) {
                sihv = POWER6_MMCRA_SIHV;
@@ -1299,13 +1330,18 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
  */
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-       unsigned long ip;
+       unsigned long mmcra = regs->dsisr;
 
+       /* Not a PMU interrupt */
        if (TRAP(regs) != 0xf00)
-               return regs->nip;       /* not a PMU interrupt */
+               return regs->nip;
+
+       /* Processor doesn't support sampling non marked events */
+       if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
+           !(mmcra & MMCRA_SAMPLE_ENABLE))
+               return regs->nip;
 
-       ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
-       return ip;
+       return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 }
 
 static bool pmc_overflow(unsigned long val)
index b4f1dda4d0896359e35d23ac497fcc4d37a5e64d..9103a1de864da338149e75a4b4e3ddc23f3f816f 100644 (file)
@@ -607,6 +607,7 @@ static struct power_pmu power4_pmu = {
        .n_generic              = ARRAY_SIZE(p4_generic_events),
        .generic_events         = p4_generic_events,
        .cache_events           = &power4_cache_events,
+       .flags                  = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
 };
 
 static int __init init_power4_pmu(void)
index 111eb25bb0b6bb22d32b89222a2a3f64c2c93339..20139ceeacf68b03009a8854adb6eb82d8dfebb9 100644 (file)
@@ -487,6 +487,7 @@ static struct power_pmu ppc970_pmu = {
        .n_generic              = ARRAY_SIZE(ppc970_generic_events),
        .generic_events         = ppc970_generic_events,
        .cache_events           = &ppc970_cache_events,
+       .flags                  = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
 };
 
 static int __init init_ppc970_pmu(void)
index eda0fc2a391454583ffaec22de12fec86e457bf8..870b70f5d1bdd2520a8bd37404eff6263278364f 100644 (file)
@@ -3,6 +3,7 @@
 #include <asm/io.h>
 #include <asm/time.h>
 #include <asm/mpc52xx.h>
+#include <asm/switch_to.h>
 
 /* defined in lite5200_sleep.S and only used here */
 extern void lite5200_low_power(void __iomem *sram, void __iomem *mbar);
index d111b024eafd0b72197d2ca40e0c047864bd299d..fb94d10e5a4d60a1c0c0c90b790d30306082df52 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/cpm2.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
-#include <asm/system.h>
 
 #include <platforms/82xx/pq2.h>
 
index 65eb792a0d001eabcdfefc04d0fc279ca7456051..a266ba8768639b8f05196fe831968ad12f8e1c61 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index e36bc611dd6e44a527c076959878c16d73228419..d440435e055cc9ac1165294688760aed8087e991 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index 39849dd1b5bbb7d827639ed1d0486bc814874ed2..a494fa57bdf9b1ef78060531e78729251a472aca 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/root_dev.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index 5828d8e97c37447a3a0ab4fbb9f8b01e8638b4fd..553e793a4a93d1b57803165b0105334de0fca75e 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/root_dev.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index ad8e4bcd7d55b412b6ad4f65552490ae67ac7031..1b1f6c8a1a12b80907ef2194be0db1bc4d31c89a 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index 8a81d7640b1fbdc0963e9e1cba3f45fe0bd256f5..26cb3e934722469d8385154c61e81d4c7decbb2c 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/root_dev.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index edf66870d978b0e4a5286e37cb74e3ab13d5c5f0..1a046715e4615fdb469ae95b81a99ba855c87e5c 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/io.h>
 #include <asm/time.h>
 #include <asm/mpc6xx.h>
+#include <asm/switch_to.h>
 
 #include <sysdev/fsl_soc.h>
 
index df69e99e511c2d04232850900116a2be84503755..dd3617c531d74260e01cbd88640e586a9f9ea2bd 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d50056f424f64aa6af1f1741c5a42b990ac00f5b..18014629416df50976ccc74e93fcb99cccc6f7ce 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 60120e55da41190d9a1d5a776a7d14e09019229e..3dc1bda3ddc31bff240f6f32b821f13856d90113 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index f58872688d8f99a01d59094eeec93d66501b8d1a..585bd22b14062b897bc18d0be1244f8e52cc4030 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d19f675cb369f886978e0763ff891aa7f1474f9d..29ee8fcd75a25046d3124beeda43c02cdb5434c2 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index ab5f0bf19454ca04526517443615b2476812e38f..11156fb53d831089f896b2c4ebbf3f94d614df06 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/atomic.h>
index 6e23e3e34bd94bf4bc501c6d6ec0ec2a142c3dd2..1fd91e9e0ffbc766452a925edd6eb8007b56a422 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index f33662b46b8d31052028c4ff779b5a4d8fc064d1..3754ddc00af709fe8290a8234a2c20b1b53d28ee 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/phy.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index db214cd4c8220ebad46e845f47de857fc7088d47..9848f9e39853fc9a06b497dae73c394c597c699c 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d8bd6563d9cac92a01d9bc7edc2236242a617787..dbaf44354f0d33a549a9ac4ed1eb0d96b24c9008 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 6b07398e4369f9ce7f1c690d3bdbc0168bfb350c..2990e8b13dc957850b0820ede1bf2633317f80ff 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index eda6ed5683e100369a354b9c3e92e515e861d2e3..6541fa2630c0114d83275cb1413d4822ddbe1b8a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 96d99a374dcf30e9e897c88f23e79242a73fd67c..f238efa75891e2099a9c5d695035292fcab853d6 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d1b21d7663e3ae6a9e8eafeb46ca2e4d2ec5d15f..c92417dc657412e2a62c9de968d8f02c8777ec70 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index e8cba5004fd822063c97e8a5ec1d4bbf9a1cb4d5..17bef15a85eda1cdce2a8acbc4353047c12c8d39 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 1677b8a22677ffe8e1d50a9497520c7babfb8823..cd3a66bdb54bcc696cf42ddcc60a744127dbf686 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/atomic.h>
index 3c3bbcc275669b45a79c4d85cd4928a9b88b7285..b1be632ede4322919c162711f61d549a0e7b3503 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index b719192177560da2fcc5fb6f8cafebb0ae283729..b9c6daa07b66a8440123b28d5acade808ec0b83d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 27ca3a7b04abb1fafa8d3346bb0d0b3378b3e2c1..e0508002b0861437021443838bcda14be97c4e43 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d7504cefe016f57912d19244f883bdf426a3b11b..4d786c25d3e514dddd5b8832e80fdf4c213c5934 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 503c21596c6328035f3799f75adc7dcd8df434f1..41c687550ea7e4f26a95bd252e901a6ea9f83f12 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index ed58b6cfd60cba66ab306876d350097dc5559c78..1fca663f1b25e90ff57dd36f6779b4dbae6208c3 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 710db69bd52314ed8f7f2d9bea5ac01c3beb87a7..14e0e576bcbd01c2ad48fd7cbc0650ad50f64f20 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 4a13d2f4ac20181a021d4794ce5fb8f554fbcdc0..1638f43599f0bbde4e73faac387d1f56c355deee 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 13fa9a6403e6fc8820554126b113038209e7fb91..bbc615206c6774d430889a76a0eb558551081437 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/seq_file.h>
 #include <linux/of.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 569262ca499a3c4d6fe06794bd47c1865ddd4b2b..3755e61d7ecfac489a8ca6837a93f49c54132782 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 22cc3571ae192ea714bdc719fc4e04641ef8d595..9982f57c98b98a0037777a8233247366f2a713bb 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/mpic.h>
 #include <asm/i8259.h>
 
index 51c8f331b6714b085a4822d620f2a3fb02f815f9..e7007d0d949e0ae73e655dc62d36fe8c4bbc02a5 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index caaec29796b748fab111247fdfa85cf1e5b1874f..866feff83c910aab87526bd661bd2fc08a4ac77f 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/8xx_immap.h>
 #include <asm/cpm1.h>
index 45ed6cdc1310ffa5373cc72784805335464a5451..5d98398c2f5e4424cf8698f7f7498b0babaffd0c 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/machdep.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
index 528e00ddef31ca46e1fb48c8bd2f691cffa3f178..8d21ab70e06c4aec26f55f67fc4d0f1574811970 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/machdep.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
index 2516c1cf8467cfd2c557a99d59b75c4114cb4b5b..943c9d39aa16f613e45d0363d4c10cc4451daca5 100644 (file)
@@ -95,7 +95,6 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
        unsigned long lpar_rc;
        u64 hpte_v, hpte_r, slot;
 
-       /* same as iseries */
        if (vflags & HPTE_V_SECONDARY)
                return -1;
 
@@ -319,7 +318,6 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
        unsigned long lpar_rc;
        u64 hpte_v, hpte_r, slot;
 
-       /* same as iseries */
        if (vflags & HPTE_V_SECONDARY)
                return -1;
 
index 4a255cf8cd17498f791befb5f1eee24db8c2ca8a..49a65e2dfc71ab2392692a810da0b984c067f37e 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/cputhreads.h>
 
index 03c5fce2a5b38b57105877608f8ddfa2a8512a5d..c2c5b078ba80457dab11d485297ba04c1b5090ef 100644 (file)
@@ -122,7 +122,7 @@ static struct spu_context *coredump_next_context(int *fd)
        struct spu_context *ctx = NULL;
 
        for (; *fd < fdt->max_fds; (*fd)++) {
-               if (!FD_ISSET(*fd, fdt->open_fds))
+               if (!fd_is_open(*fd, fdt))
                        continue;
 
                file = fcheck(*fd);
index 8cab5731850f4f9a7a8fad46fb408725c5fffcee..ebd3963fdf911bf256d180df98cec93772c3fa44 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/time.h>
 
 #include <mm/mmu_decl.h>
index ab51b21b4bd75bd4aea1ebef19f452cb8ab50a56..8c305c7c8977dbffc4edd142b5d77d83ed142d78 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/of_platform.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
index 74ccce36baedc8039570c6153b3b73c5a607780a..beeaf4a173e15ada794aa02ed256aeabe5a13b83 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/tty.h>
 #include <linux/serial_core.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
index 670035f49a6959c72af1b59ad800eab3edf631c6..d455f08bea53939e021219d3bb406cf1b18f9dc7 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/time.h>
 
 #include <mm/mmu_decl.h>
index e0ed3c71d69b8d5896fcdef23d5bc84e6fb753d0..c458b60d14c4f78064485f209a026438e73f1e9a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/initrd.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/mpic.h>
index 8b0c2082a78305967c2f05089add88a2a6d3965b..64fde058e54570d812de8501631e4ebb03863584 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 
-#include <asm/system.h>
 #include <asm/pci-bridge.h>
 
 #define ULI_PIRQA      0x08
index 3b7545a51aa9af5fd4d5d450c5e2e694f8395e3e..cb1b0b35a0c6ea66dd223e00d6fc7b6f0b93e458 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/processor.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
index eac569dee27cc0d576069ddbd933520121ff681d..b4a369dac3a8aea479580187f7ace7fbe5ce8704 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
index e777ad471a48797f2cabd24969afaaee09e1c1f5..2ed9212d7d59a56aec67df3e631288c0864b5a78 100644 (file)
 #include <linux/gfp.h>
 
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/mpic.h>
 #include <asm/smp.h>
 #include <asm/time.h>
 #include <asm/mmu.h>
+#include <asm/debug.h>
 
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
index 84d7fd9bcc696ecbb2f5c94fc06c33ab25395557..3e91ef538114c6adb14401b6e33b5b247f5aa3e4 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 #undef DEBUG
 #define SET_BOOT_BAT
index 1fc386a23f18740ec2308b9ce05a026ec5adab25..64171198535ce7b181e6c67cdfb5d195514d588c 100644 (file)
@@ -33,9 +33,9 @@
 #include <asm/sections.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#include <asm/system.h>
 #include <asm/mpic.h>
 #include <asm/keylargo.h>
+#include <asm/switch_to.h>
 
 /* WARNING !!! This will cause calibrate_delay() to be called,
  * but this is an __init function ! So you MUST go edit
index da18b26dcc6fdafb3136a8d8df030eff1c92f89b..014d06e6d46b88922e29367d26a227dbeef7c573 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/spinlock.h>
 #include <asm/sections.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/nvram.h>
index 970ea1de4298c0cf0a1166974352aa61d03286dd..141f8899a633f04182d65179c410b53a78a74109 100644 (file)
@@ -57,7 +57,6 @@
 #include <asm/reg.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
index 11c9fce43b5b876a5078e1731a785d962137aeb9..8680bb69795d3e6f0c0a43edb47ad72ac2d96b62 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
index 17210c526c523c823ba949e963a6c47158189bdd..3ef46254c35ba907dfd9329f9164db3176a9d7a4 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/vdso_datapage.h>
 #include <asm/cputhreads.h>
index 8bd6ba542691e7674b29e275339b36e43539d5bc..de2aea421707137a458509bfb33dfc62bb720fd8 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
+#include <asm/setup.h>
 
 #include "platform.h"
 
index 0e8656370063fe6bf005e59032a67c414efe729f..a7648543c59e05435eac37c5099eeda84db9584d 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/spinlock.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
 #include <asm/lppaca.h>
+#include <asm/debug.h>
 
 #include "plpar_wrappers.h"
 
index 8011088392d3421cf560ae4a173fde92eb54f1b1..309d38ef732209ce68ec99380ef09b97d5bfc41f 100644 (file)
@@ -984,7 +984,8 @@ int __exit eeh_ops_unregister(const char *name)
  */
 void __init eeh_init(void)
 {
-       struct device_node *phb, *np;
+       struct pci_controller *hose, *tmp;
+       struct device_node *phb;
        int ret;
 
        /* call platform initialization function */
@@ -1000,19 +1001,9 @@ void __init eeh_init(void)
 
        raw_spin_lock_init(&confirm_error_lock);
 
-       np = of_find_node_by_path("/rtas");
-       if (np == NULL)
-               return;
-
-       /* Enable EEH for all adapters.  Note that eeh requires buid's */
-       for (phb = of_find_node_by_name(NULL, "pci"); phb;
-            phb = of_find_node_by_name(phb, "pci")) {
-               unsigned long buid;
-
-               buid = get_phb_buid(phb);
-               if (buid == 0 || !of_node_to_eeh_dev(phb))
-                       continue;
-
+       /* Enable EEH for all adapters */
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               phb = hose->dn;
                traverse_pci_devices(phb, eeh_early_enable, NULL);
        }
 
index f3aed7dcae9528212d100357d0d2632935e64a5c..c4507d09590029f94726b7b3afaeebba29b276aa 100644 (file)
@@ -62,7 +62,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
        }
 
        /* Associate EEH device with OF node */
-       dn->edev  = edev;
+       PCI_DN(dn)->edev = edev;
        edev->dn  = dn;
        edev->phb = phb;
 
index c986d08d0807d91a36c7a927cdbd807ba3ed1276..64c97d8ac0c563d9f14da2ae2f0f4cd0c8c80b82 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/sched.h>       /* for idle_task_exit */
 #include <linux/cpu.h>
-#include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/firmware.h>
index 1a709bc48ce18c89acca256e56d2930ad661f58f..ef9d9d84c7d5d7ee3b1c1220c1d2d080e2dd1f98 100644 (file)
@@ -63,72 +63,8 @@ EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list);
 
 static int ioei_check_exception_token;
 
-/* pSeries event log format */
-
-/* Two bytes ASCII section IDs */
-#define PSERIES_ELOG_SECT_ID_PRIV_HDR          (('P' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_USER_HDR          (('U' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_PRIMARY_SRC       (('P' << 8) | 'S')
-#define PSERIES_ELOG_SECT_ID_EXTENDED_UH       (('E' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_FAILING_MTMS      (('M' << 8) | 'T')
-#define PSERIES_ELOG_SECT_ID_SECONDARY_SRC     (('S' << 8) | 'S')
-#define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR      (('D' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_FW_ERROR          (('S' << 8) | 'W')
-#define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID    (('L' << 8) | 'P')
-#define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R')
-#define PSERIES_ELOG_SECT_ID_HMC_ID            (('H' << 8) | 'M')
-#define PSERIES_ELOG_SECT_ID_EPOW              (('E' << 8) | 'P')
-#define PSERIES_ELOG_SECT_ID_IO_EVENT          (('I' << 8) | 'E')
-#define PSERIES_ELOG_SECT_ID_MANUFACT_INFO     (('M' << 8) | 'I')
-#define PSERIES_ELOG_SECT_ID_CALL_HOME         (('C' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_USER_DEF          (('U' << 8) | 'D')
-
-/* Vendor specific Platform Event Log Format, Version 6, section header */
-struct pseries_elog_section {
-       uint16_t id;                    /* 0x00 2-byte ASCII section ID */
-       uint16_t length;                /* 0x02 Section length in bytes */
-       uint8_t version;                /* 0x04 Section version         */
-       uint8_t subtype;                /* 0x05 Section subtype         */
-       uint16_t creator_component;     /* 0x06 Creator component ID    */
-       uint8_t data[];                 /* 0x08 Start of section data   */
-};
-
 static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
 
-/**
- * Find data portion of a specific section in RTAS extended event log.
- * @elog: RTAS error/event log.
- * @sect_id: secsion ID.
- *
- * Return:
- *     pointer to the section data of the specified section
- *     NULL if not found
- */
-static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *elog,
-                                                      uint16_t sect_id)
-{
-       struct rtas_ext_event_log_v6 *xelog =
-               (struct rtas_ext_event_log_v6 *) elog->buffer;
-       struct pseries_elog_section *sect;
-       unsigned char *p, *log_end;
-
-       /* Check that we understand the format */
-       if (elog->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
-           xelog->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
-           xelog->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
-               return NULL;
-
-       log_end = elog->buffer + elog->extended_log_length;
-       p = xelog->vendor_log;
-       while (p < log_end) {
-               sect = (struct pseries_elog_section *)p;
-               if (sect->id == sect_id)
-                       return sect;
-               p += sect->length;
-       }
-       return NULL;
-}
-
 /**
  * Find the data portion of an IO Event section from event log.
  * @elog: RTAS error/event log.
@@ -138,7 +74,7 @@ static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *el
  */
 static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
 {
-       struct pseries_elog_section *sect;
+       struct pseries_errorlog *sect;
 
        /* We should only ever get called for io-event interrupts, but if
         * we do get called for another type then something went wrong so
@@ -152,7 +88,7 @@ static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
                return NULL;
        }
 
-       sect = find_xelog_section(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
+       sect = get_pseries_errorlog(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
        if (unlikely(!sect)) {
                printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
                            "log does not contain an IO Event section. "
index c442f2b1980ffc0a74e421c97d8ac9e2c9407ab5..0915b1ad66ce0dbb9e893ddd54a51753029e8a67 100644 (file)
@@ -809,8 +809,7 @@ machine_arch_initcall(pseries, find_existing_ddw_windows);
 static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
                        struct ddw_query_response *query)
 {
-       struct device_node *dn;
-       struct pci_dn *pcidn;
+       struct eeh_dev *edev;
        u32 cfg_addr;
        u64 buid;
        int ret;
@@ -821,12 +820,12 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
         * Retrieve them from the pci device, not the node with the
         * dma-window property
         */
-       dn = pci_device_to_OF_node(dev);
-       pcidn = PCI_DN(dn);
-       cfg_addr = pcidn->eeh_config_addr;
-       if (pcidn->eeh_pe_config_addr)
-               cfg_addr = pcidn->eeh_pe_config_addr;
-       buid = pcidn->phb->buid;
+       edev = pci_dev_to_eeh_dev(dev);
+       cfg_addr = edev->config_addr;
+       if (edev->pe_config_addr)
+               cfg_addr = edev->pe_config_addr;
+       buid = edev->phb->buid;
+
        ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
                  cfg_addr, BUID_HI(buid), BUID_LO(buid));
        dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
@@ -839,8 +838,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
                        struct ddw_create_response *create, int page_shift,
                        int window_shift)
 {
-       struct device_node *dn;
-       struct pci_dn *pcidn;
+       struct eeh_dev *edev;
        u32 cfg_addr;
        u64 buid;
        int ret;
@@ -851,12 +849,11 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
         * Retrieve them from the pci device, not the node with the
         * dma-window property
         */
-       dn = pci_device_to_OF_node(dev);
-       pcidn = PCI_DN(dn);
-       cfg_addr = pcidn->eeh_config_addr;
-       if (pcidn->eeh_pe_config_addr)
-               cfg_addr = pcidn->eeh_pe_config_addr;
-       buid = pcidn->phb->buid;
+       edev = pci_dev_to_eeh_dev(dev);
+       cfg_addr = edev->config_addr;
+       if (edev->pe_config_addr)
+               cfg_addr = edev->pe_config_addr;
+       buid = edev->phb->buid;
 
        do {
                /* extra outputs are LIOBN and dma-addr (hi, lo) */
index a12e95af69331cfa7e54147405699cfb3adca738..41a34bc4a9a2903e3d9bb747176cfde009f16435 100644 (file)
@@ -14,9 +14,9 @@
 
 #include <asm/paca.h>
 #include <asm/reg.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/runlatch.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
index 086d2ae4e06a2c322b43409395e514cab30179af..c4dfccd3a3d90bf6f4a24e0377f2a890eacb57db 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-/* Change Activity:
- * 2001/09/21 : engebret : Created with minimal EPOW and HW exception support.
- * End Change Activity
- */
-
-#include <linux/errno.h>
-#include <linux/threads.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/random.h>
-#include <linux/sysrq.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/cache.h>
-#include <asm/prom.h>
-#include <asm/ptrace.h>
+#include <linux/of.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+
 #include <asm/machdep.h>
 #include <asm/rtas.h>
-#include <asm/udbg.h>
 #include <asm/firmware.h>
 
 #include "pseries.h"
@@ -57,7 +35,6 @@ static DEFINE_SPINLOCK(ras_log_buf_lock);
 static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
 static DEFINE_PER_CPU(__u64, mce_data_buf);
 
-static int ras_get_sensor_state_token;
 static int ras_check_exception_token;
 
 #define EPOW_SENSOR_TOKEN      9
@@ -75,7 +52,6 @@ static int __init init_ras_IRQ(void)
 {
        struct device_node *np;
 
-       ras_get_sensor_state_token = rtas_token("get-sensor-state");
        ras_check_exception_token = rtas_token("check-exception");
 
        /* Internal Errors */
@@ -95,26 +71,126 @@ static int __init init_ras_IRQ(void)
 
        return 0;
 }
-__initcall(init_ras_IRQ);
+subsys_initcall(init_ras_IRQ);
 
-/*
- * Handle power subsystem events (EPOW).
- *
- * Presently we just log the event has occurred.  This should be fixed
- * to examine the type of power failure and take appropriate action where
- * the time horizon permits something useful to be done.
- */
+#define EPOW_SHUTDOWN_NORMAL                           1
+#define EPOW_SHUTDOWN_ON_UPS                           2
+#define EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS       3
+#define EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH     4
+
+static void handle_system_shutdown(char event_modifier)
+{
+       switch (event_modifier) {
+       case EPOW_SHUTDOWN_NORMAL:
+               pr_emerg("Firmware initiated power off");
+               orderly_poweroff(1);
+               break;
+
+       case EPOW_SHUTDOWN_ON_UPS:
+               pr_emerg("Loss of power reported by firmware, system is "
+                       "running on UPS/battery");
+               break;
+
+       case EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS:
+               pr_emerg("Loss of system critical functions reported by "
+                       "firmware");
+               pr_emerg("Check RTAS error log for details");
+               orderly_poweroff(1);
+               break;
+
+       case EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH:
+               pr_emerg("Ambient temperature too high reported by firmware");
+               pr_emerg("Check RTAS error log for details");
+               orderly_poweroff(1);
+               break;
+
+       default:
+               pr_err("Unknown power/cooling shutdown event (modifier %d)",
+                       event_modifier);
+       }
+}
+
+struct epow_errorlog {
+       unsigned char sensor_value;
+       unsigned char event_modifier;
+       unsigned char extended_modifier;
+       unsigned char reserved;
+       unsigned char platform_reason;
+};
+
+#define EPOW_RESET                     0
+#define EPOW_WARN_COOLING              1
+#define EPOW_WARN_POWER                        2
+#define EPOW_SYSTEM_SHUTDOWN           3
+#define EPOW_SYSTEM_HALT               4
+#define EPOW_MAIN_ENCLOSURE            5
+#define EPOW_POWER_OFF                 7
+
+void rtas_parse_epow_errlog(struct rtas_error_log *log)
+{
+       struct pseries_errorlog *pseries_log;
+       struct epow_errorlog *epow_log;
+       char action_code;
+       char modifier;
+
+       pseries_log = get_pseries_errorlog(log, PSERIES_ELOG_SECT_ID_EPOW);
+       if (pseries_log == NULL)
+               return;
+
+       epow_log = (struct epow_errorlog *)pseries_log->data;
+       action_code = epow_log->sensor_value & 0xF;     /* bottom 4 bits */
+       modifier = epow_log->event_modifier & 0xF;      /* bottom 4 bits */
+
+       switch (action_code) {
+       case EPOW_RESET:
+               pr_err("Non critical power or cooling issue cleared");
+               break;
+
+       case EPOW_WARN_COOLING:
+               pr_err("Non critical cooling issue reported by firmware");
+               pr_err("Check RTAS error log for details");
+               break;
+
+       case EPOW_WARN_POWER:
+               pr_err("Non critical power issue reported by firmware");
+               pr_err("Check RTAS error log for details");
+               break;
+
+       case EPOW_SYSTEM_SHUTDOWN:
+               handle_system_shutdown(epow_log->event_modifier);
+               break;
+
+       case EPOW_SYSTEM_HALT:
+               pr_emerg("Firmware initiated power off");
+               orderly_poweroff(1);
+               break;
+
+       case EPOW_MAIN_ENCLOSURE:
+       case EPOW_POWER_OFF:
+               pr_emerg("Critical power/cooling issue reported by firmware");
+               pr_emerg("Check RTAS error log for details");
+               pr_emerg("Immediate power off");
+               emergency_sync();
+               kernel_power_off();
+               break;
+
+       default:
+               pr_err("Unknown power/cooling event (action code %d)",
+                       action_code);
+       }
+}
+
+/* Handle environmental and power warning (EPOW) interrupts. */
 static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 {
-       int status = 0xdeadbeef;
-       int state = 0;
+       int status;
+       int state;
        int critical;
 
-       status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
-                          EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
+       status = rtas_get_sensor(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX, &state);
 
        if (state > 3)
-               critical = 1;  /* Time Critical */
+               critical = 1;           /* Time Critical */
        else
                critical = 0;
 
@@ -123,18 +199,14 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
        status = rtas_call(ras_check_exception_token, 6, 1, NULL,
                           RTAS_VECTOR_EXTERNAL_INTERRUPT,
                           virq_to_hw(irq),
-                          RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
+                          RTAS_EPOW_WARNING,
                           critical, __pa(&ras_log_buf),
                                rtas_get_error_log_max());
 
-       udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
-                   *((unsigned long *)&ras_log_buf), status, state);
-       printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
-              *((unsigned long *)&ras_log_buf), status, state);
-
-       /* format and print the extended information */
        log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
 
+       rtas_parse_epow_errlog((struct rtas_error_log *)ras_log_buf);
+
        spin_unlock(&ras_log_buf_lock);
        return IRQ_HANDLED;
 }
@@ -150,7 +222,7 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 {
        struct rtas_error_log *rtas_elog;
-       int status = 0xdeadbeef;
+       int status;
        int fatal;
 
        spin_lock(&ras_log_buf_lock);
@@ -158,7 +230,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
        status = rtas_call(ras_check_exception_token, 6, 1, NULL,
                           RTAS_VECTOR_EXTERNAL_INTERRUPT,
                           virq_to_hw(irq),
-                          RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
+                          RTAS_INTERNAL_ERROR, 1 /* Time Critical */,
                           __pa(&ras_log_buf),
                                rtas_get_error_log_max());
 
@@ -173,24 +245,13 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
        log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
 
        if (fatal) {
-               udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
-                           *((unsigned long *)&ras_log_buf), status);
-               printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
-                      *((unsigned long *)&ras_log_buf), status);
-
-#ifndef DEBUG_RTAS_POWER_OFF
-               /* Don't actually power off when debugging so we can test
-                * without actually failing while injecting errors.
-                * Error data will not be logged to syslog.
-                */
-               ppc_md.power_off();
-#endif
+               pr_emerg("Fatal hardware error reported by firmware");
+               pr_emerg("Check RTAS error log for details");
+               pr_emerg("Immediate power off");
+               emergency_sync();
+               kernel_power_off();
        } else {
-               udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
-                           *((unsigned long *)&ras_log_buf), status);
-               printk(KERN_WARNING
-                      "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
-                      *((unsigned long *)&ras_log_buf), status);
+               pr_err("Recoverable hardware error reported by firmware");
        }
 
        spin_unlock(&ras_log_buf_lock);
index eadba9521a359968a524d448d458cdd92e96e278..e16bb8d48550b60e249ade3aac24b00ed2159233 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/mpic.h>
index ca6fa26f6e631d207fb6c665675640ab7bc33aa5..8ef53bc2e70e2e442962820382f4664b62aa7a34 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/time.h>
 
 #include <asm/machdep.h>
-#include <asm/system.h>
 #include <asm/udbg.h>
 
 #include "ics.h"
index 0c1ae06d0be1d82f39ad43d4ca0b03e387577641..508ec8282b96f7e2d67641619d48d43f3917f808 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/time.h>
 
 #include <asm/machdep.h>
-#include <asm/system.h>
 #include <asm/udbg.h>
 
 #include "ics.h"
index 763014cd1e622783bbc5e4410d89ce7525c9cc60..1526551f9fe6b5541f08b15d8bbf343537c3d298 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/ppc-pci.h>
 #include <asm/iommu.h>
 #include <asm/io-workarounds.h>
+#include <asm/debug.h>
 
 #include "wsp.h"
 #include "wsp_pci.h"
index bf6c7cc0a6afd55cbb9da1afae5f8add42e82f30..4dd534194ae8b889290ae9b62403aa05f41438c6 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/udbg.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/rheap.h>
 #include <asm/cpm.h>
 
index e8f385fbf54967abb88aaa81261e2672037fe294..c449dbd1c938f749447bf04944dde0e6ca1450e1 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index 5287e95cec3a5ad79e6e6f9997335a3f0abd2e45..0968b66b4cf96bc25b73c92a2c7f1fb4bdfa3605 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/bitmap.h>
 #include <asm/msi_bitmap.h>
+#include <asm/setup.h>
 
 int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num)
 {
index 2370e1c633795fbb328a32e7878b860f34232288..1fd0717ade02dd2049800ef0c0bc51cbbac28a71 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_net.h>
 #include <asm/tsi108.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index 68a9cbbab4504de8b7b5844047e89ce31a075c60..0f3ab06d222260c63d5866e6d6b7ab0ac643e761 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/spu_priv1.h>
 #include <asm/setjmp.h>
 #include <asm/reg.h>
+#include <asm/debug.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
index 465d5be1f0f4fd76ddef6fcac7fe301dd0d4c060..2b7c0fbe578e3341a8d52e98f9cfced0a82023df 100644 (file)
@@ -219,6 +219,7 @@ config COMPAT
        prompt "Kernel support for 31 bit emulation"
        depends on 64BIT
        select COMPAT_BINFMT_ELF
+       select ARCH_WANT_OLD_COMPAT_IPC
        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
index ffd1ac255f19444d838e58b2fb2ef2b716b02f77..9178db6db0a5abaa44055f0f5224632513d97976 100644 (file)
@@ -17,6 +17,7 @@
 #define _CRYPTO_ARCH_S390_CRYPT_S390_H
 
 #include <asm/errno.h>
+#include <asm/facility.h>
 
 #define CRYPT_S390_OP_MASK 0xFF00
 #define CRYPT_S390_FUNC_MASK 0x00FF
index 8517d2ae3b5ca40ece8067ce2338b2afa9bc2577..748347baecb8da6a9b22fb3daad326302c517ef0 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..451273a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * This is very similar to the ppc eieio/sync instruction in that is
+ * does a checkpoint syncronisation & makes sure that 
+ * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
+ */
+
+#define eieio()        asm volatile("bcr 15,0" : : : "memory")
+#define SYNC_OTHER_CORES(x)   eieio()
+#define mb()    eieio()
+#define rmb()   eieio()
+#define wmb()   eieio()
+#define read_barrier_depends() do { } while(0)
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()    read_barrier_depends()
+#define smp_mb__before_clear_bit()     smp_mb()
+#define smp_mb__after_clear_bit()      smp_mb()
+
+#define set_mb(var, value)      do { var = value; mb(); } while (0)
+
+#endif /* __ASM_BARRIER_H */
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
new file mode 100644 (file)
index 0000000..ecde941
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_CTL_REG_H
+#define __ASM_CTL_REG_H
+
+#ifdef __s390x__
+
+#define __ctl_load(array, low, high) ({                                \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       lctlg   %1,%2,%0\n"                     \
+               : : "Q" (*(addrtype *)(&array)),                \
+                   "i" (low), "i" (high));                     \
+       })
+
+#define __ctl_store(array, low, high) ({                       \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       stctg   %1,%2,%0\n"                     \
+               : "=Q" (*(addrtype *)(&array))                  \
+               : "i" (low), "i" (high));                       \
+       })
+
+#else /* __s390x__ */
+
+#define __ctl_load(array, low, high) ({                                \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       lctl    %1,%2,%0\n"                     \
+               : : "Q" (*(addrtype *)(&array)),                \
+                   "i" (low), "i" (high));                     \
+})
+
+#define __ctl_store(array, low, high) ({                       \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       stctl   %1,%2,%0\n"                     \
+               : "=Q" (*(addrtype *)(&array))                  \
+               : "i" (low), "i" (high));                       \
+       })
+
+#endif /* __s390x__ */
+
+#define __ctl_set_bit(cr, bit) ({      \
+       unsigned long __dummy;          \
+       __ctl_store(__dummy, cr, cr);   \
+       __dummy |= 1UL << (bit);        \
+       __ctl_load(__dummy, cr, cr);    \
+})
+
+#define __ctl_clear_bit(cr, bit) ({    \
+       unsigned long __dummy;          \
+       __ctl_store(__dummy, cr, cr);   \
+       __dummy &= ~(1UL << (bit));     \
+       __ctl_load(__dummy, cr, cr);    \
+})
+
+#ifdef CONFIG_SMP
+
+extern void smp_ctl_set_bit(int cr, int bit);
+extern void smp_ctl_clear_bit(int cr, int bit);
+#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
+
+#else
+
+#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASM_CTL_REG_H */
index 547f1a6a35d442534c7027d316985b015fb00f06..c4ee39f7a4d6a12895f6f3a8bf8b862b83ea9e4d 100644 (file)
@@ -129,7 +129,6 @@ typedef s390_fp_regs compat_elf_fpregset_t;
 typedef s390_compat_regs compat_elf_gregset_t;
 
 #include <linux/sched.h>       /* for task_struct */
-#include <asm/system.h>                /* for save_access_regs */
 #include <asm/mmu_context.h>
 
 #include <asm/vdso.h>
diff --git a/arch/s390/include/asm/exec.h b/arch/s390/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c4a93d6
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_EXEC_H
+#define __ASM_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* __ASM_EXEC_H */
diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h
new file mode 100644 (file)
index 0000000..1e5b27e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_FACILITY_H
+#define __ASM_FACILITY_H
+
+#include <linux/string.h>
+#include <linux/preempt.h>
+#include <asm/lowcore.h>
+
+#define MAX_FACILITY_BIT (256*8)       /* stfle_fac_list has 256 bytes */
+
+/*
+ * The test_facility function uses the bit odering where the MSB is bit 0.
+ * That makes it easier to query facility bits with the bit number as
+ * documented in the Principles of Operation.
+ */
+static inline int test_facility(unsigned long nr)
+{
+       unsigned char *ptr;
+
+       if (nr >= MAX_FACILITY_BIT)
+               return 0;
+       ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3);
+       return (*ptr & (0x80 >> (nr & 7))) != 0;
+}
+
+/**
+ * stfle - Store facility list extended
+ * @stfle_fac_list: array where facility list can be stored
+ * @size: size of passed in array in double words
+ */
+static inline void stfle(u64 *stfle_fac_list, int size)
+{
+       unsigned long nr;
+
+       preempt_disable();
+       S390_lowcore.stfl_fac_list = 0;
+       asm volatile(
+               "       .insn s,0xb2b10000,0(0)\n" /* stfl */
+               "0:\n"
+               EX_TABLE(0b, 0b)
+               : "=m" (S390_lowcore.stfl_fac_list));
+       nr = 4; /* bytes stored by stfl */
+       memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
+       if (S390_lowcore.stfl_fac_list & 0x01000000) {
+               /* More facility bits available with stfle */
+               register unsigned long reg0 asm("0") = size - 1;
+
+               asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
+                            : "+d" (reg0)
+                            : "a" (stfle_fac_list)
+                            : "memory", "cc");
+               nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
+       }
+       memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
+       preempt_enable();
+}
+
+#endif /* __ASM_FACILITY_H */
index 82b32a100c7ddc18f69547ca40ec946e873852c6..96076676e22481b72b9cb20914a9857f0b12e325 100644 (file)
@@ -41,4 +41,15 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
+#define KVM_SYNC_PREFIX (1UL << 0)
+#define KVM_SYNC_GPRS   (1UL << 1)
+#define KVM_SYNC_ACRS   (1UL << 2)
+#define KVM_SYNC_CRS    (1UL << 3)
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+       __u64 prefix;   /* prefix register */
+       __u64 gprs[16]; /* general purpose registers */
+       __u32 acrs[16]; /* access registers */
+       __u64 crs[16];  /* control registers */
+};
 #endif
index b0c235cb6ad5c79d42414a863508e0c37db8337d..7343872890a25a692eb7925f3a5904e640408880 100644 (file)
@@ -220,18 +220,17 @@ struct kvm_s390_float_interrupt {
        struct list_head list;
        atomic_t active;
        int next_rr_cpu;
-       unsigned long idle_mask [(64 + sizeof(long) - 1) / sizeof(long)];
-       struct kvm_s390_local_interrupt *local_int[64];
+       unsigned long idle_mask[(KVM_MAX_VCPUS + sizeof(long) - 1)
+                               / sizeof(long)];
+       struct kvm_s390_local_interrupt *local_int[KVM_MAX_VCPUS];
 };
 
 
 struct kvm_vcpu_arch {
        struct kvm_s390_sie_block *sie_block;
-       unsigned long     guest_gprs[16];
        s390_fp_regs      host_fpregs;
        unsigned int      host_acrs[NUM_ACRS];
        s390_fp_regs      guest_fpregs;
-       unsigned int      guest_acrs[NUM_ACRS];
        struct kvm_s390_local_interrupt local_int;
        struct hrtimer    ckc_timer;
        struct tasklet_struct tasklet;
@@ -246,6 +245,9 @@ struct kvm_vm_stat {
        u32 remote_tlb_flush;
 };
 
+struct kvm_arch_memory_slot {
+};
+
 struct kvm_arch{
        struct sca_block *sca;
        debug_info_t *dbf;
@@ -253,5 +255,5 @@ struct kvm_arch{
        struct gmap *gmap;
 };
 
-extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
+extern int sie64a(struct kvm_s390_sie_block *, u64 *);
 #endif
index 4506791adcd5cf5db044b405cb4c9f6f24398f74..1c7d6ce328bf6bfe52cf715ac8680c2143a2dc76 100644 (file)
@@ -21,4 +21,18 @@ typedef struct {
        .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),    \
        .context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
 
+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;
+}
+
 #endif
index 5682f160ff82caa965a9bd1e3c3aa0b28d403021..5d09e405c54d504a8e3a243b54155d91eb8e18db 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
+#include <asm/ctl_reg.h>
 #include <asm-generic/mm_hooks.h>
 
 static inline int init_new_context(struct task_struct *tsk,
index 8cc113f9252352d3070ee4f03c0bb5a9aa833f7a..edf8527ff08d9bdf9e5f0468e24faebfdd372c34 100644 (file)
@@ -3,7 +3,6 @@
  *
  *  S390 version
  *
- *  Derived from "include/asm-i386/posix_types.h"
  */
 
 #ifndef __ARCH_S390_POSIX_TYPES_H
  * assume GCC is being used.
  */
 
-typedef long            __kernel_off_t;
-typedef int             __kernel_pid_t;
 typedef unsigned long   __kernel_size_t;
-typedef long            __kernel_time_t;
-typedef long            __kernel_suseconds_t;
-typedef long            __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int             __kernel_daddr_t;
-typedef char *          __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
+#define __kernel_size_t __kernel_size_t
 
-#ifdef __GNUC__
-typedef long long       __kernel_loff_t;
-#endif
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
 #ifndef __s390x__
 
@@ -42,11 +30,6 @@ typedef unsigned short  __kernel_uid_t;
 typedef unsigned short  __kernel_gid_t;
 typedef int             __kernel_ssize_t;
 typedef int             __kernel_ptrdiff_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
 
 #else /* __s390x__ */
 
@@ -59,49 +42,16 @@ typedef unsigned int    __kernel_gid_t;
 typedef long            __kernel_ssize_t;
 typedef long            __kernel_ptrdiff_t;
 typedef unsigned long   __kernel_sigset_t;      /* at least 32 bits */
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
-typedef unsigned short __kernel_old_dev_t;
 
 #endif /* __s390x__ */
 
-typedef struct {
-        int     val[2];
-} __kernel_fsid_t;
-
-
-#ifdef __KERNEL__
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (fdsetp->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-#undef  __FD_ZERO
-#define __FD_ZERO(fdsetp) \
-       ((void) memset ((void *) (fdsetp), 0, sizeof (__kernel_fd_set)))
+#define __kernel_ino_t  __kernel_ino_t
+#define __kernel_mode_t __kernel_mode_t
+#define __kernel_nlink_t __kernel_nlink_t
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+#define __kernel_uid_t __kernel_uid_t
+#define __kernel_gid_t __kernel_gid_t
 
-#endif     /* __KERNEL__ */
+#include <asm-generic/posix_types.h>
 
 #endif
index d25843a6a91512409aca2d56458d06cd9f90922f..d499b30ea487107b339c252dff39bf3ae5c9dfe9 100644 (file)
@@ -14,6 +14,7 @@
 #define __ASM_S390_PROCESSOR_H
 
 #include <linux/linkage.h>
+#include <linux/irqflags.h>
 #include <asm/cpu.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -156,6 +157,14 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->psw.addr)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->gprs[15])
 
+static inline unsigned short stap(void)
+{
+       unsigned short cpu_address;
+
+       asm volatile("stap %0" : "=m" (cpu_address));
+       return cpu_address;
+}
+
 /*
  * Give up the time slice of the virtual PU.
  */
@@ -303,6 +312,21 @@ static inline void __noreturn disabled_wait(unsigned long code)
        while (1);
 }
 
+/*
+ * Use to set psw mask except for the first byte which
+ * won't be changed by this function.
+ */
+static inline void
+__set_psw_mask(unsigned long mask)
+{
+       __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
+}
+
+#define local_mcck_enable() \
+       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+#define local_mcck_disable() \
+       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
+
 /*
  * Basic Machine Check/Program Check Handler.
  */
index 097183c70407a81e9147697a37c880a6008b4ed1..b21e46e5d4b8379994949d447499221c2ffb96cd 100644 (file)
@@ -140,6 +140,20 @@ extern char vmpoff_cmd[];
 #define NSS_NAME_SIZE  8
 extern char kernel_nss_name[];
 
+#ifdef CONFIG_PFAULT
+extern int pfault_init(void);
+extern void pfault_fini(void);
+#else /* CONFIG_PFAULT */
+#define pfault_init()          ({-1;})
+#define pfault_fini()          do { } while (0)
+#endif /* CONFIG_PFAULT */
+
+extern void cmma_init(void);
+
+extern void (*_machine_restart)(char *command);
+extern void (*_machine_halt)(void);
+extern void (*_machine_power_off)(void);
+
 #else /* __ASSEMBLY__ */
 
 #ifndef __s390x__
index 797f7872968020aa26430e72b847c6ec8a2ee887..c77c6de6f6c0d9dbb4da4b39dcfc5583f3b01b02 100644 (file)
@@ -9,7 +9,7 @@
 
 #ifdef CONFIG_SMP
 
-#include <asm/system.h>
+#include <asm/lowcore.h>
 
 #define raw_smp_processor_id() (S390_lowcore.cpu_nr)
 
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..f223068
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_SWITCH_TO_H
+#define __ASM_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+extern struct task_struct *__switch_to(void *, void *);
+extern void update_per_regs(struct task_struct *task);
+
+static inline void save_fp_regs(s390_fp_regs *fpregs)
+{
+       asm volatile(
+               "       std     0,%O0+8(%R0)\n"
+               "       std     2,%O0+24(%R0)\n"
+               "       std     4,%O0+40(%R0)\n"
+               "       std     6,%O0+56(%R0)"
+               : "=Q" (*fpregs) : "Q" (*fpregs));
+       if (!MACHINE_HAS_IEEE)
+               return;
+       asm volatile(
+               "       stfpc   %0\n"
+               "       std     1,%O0+16(%R0)\n"
+               "       std     3,%O0+32(%R0)\n"
+               "       std     5,%O0+48(%R0)\n"
+               "       std     7,%O0+64(%R0)\n"
+               "       std     8,%O0+72(%R0)\n"
+               "       std     9,%O0+80(%R0)\n"
+               "       std     10,%O0+88(%R0)\n"
+               "       std     11,%O0+96(%R0)\n"
+               "       std     12,%O0+104(%R0)\n"
+               "       std     13,%O0+112(%R0)\n"
+               "       std     14,%O0+120(%R0)\n"
+               "       std     15,%O0+128(%R0)\n"
+               : "=Q" (*fpregs) : "Q" (*fpregs));
+}
+
+static inline void restore_fp_regs(s390_fp_regs *fpregs)
+{
+       asm volatile(
+               "       ld      0,%O0+8(%R0)\n"
+               "       ld      2,%O0+24(%R0)\n"
+               "       ld      4,%O0+40(%R0)\n"
+               "       ld      6,%O0+56(%R0)"
+               : : "Q" (*fpregs));
+       if (!MACHINE_HAS_IEEE)
+               return;
+       asm volatile(
+               "       lfpc    %0\n"
+               "       ld      1,%O0+16(%R0)\n"
+               "       ld      3,%O0+32(%R0)\n"
+               "       ld      5,%O0+48(%R0)\n"
+               "       ld      7,%O0+64(%R0)\n"
+               "       ld      8,%O0+72(%R0)\n"
+               "       ld      9,%O0+80(%R0)\n"
+               "       ld      10,%O0+88(%R0)\n"
+               "       ld      11,%O0+96(%R0)\n"
+               "       ld      12,%O0+104(%R0)\n"
+               "       ld      13,%O0+112(%R0)\n"
+               "       ld      14,%O0+120(%R0)\n"
+               "       ld      15,%O0+128(%R0)\n"
+               : : "Q" (*fpregs));
+}
+
+static inline void save_access_regs(unsigned int *acrs)
+{
+       asm volatile("stam 0,15,%0" : "=Q" (*acrs));
+}
+
+static inline void restore_access_regs(unsigned int *acrs)
+{
+       asm volatile("lam 0,15,%0" : : "Q" (*acrs));
+}
+
+#define switch_to(prev,next,last) do {                                 \
+       if (prev->mm) {                                                 \
+               save_fp_regs(&prev->thread.fp_regs);                    \
+               save_access_regs(&prev->thread.acrs[0]);                \
+       }                                                               \
+       if (next->mm) {                                                 \
+               restore_fp_regs(&next->thread.fp_regs);                 \
+               restore_access_regs(&next->thread.acrs[0]);             \
+               update_per_regs(next);                                  \
+       }                                                               \
+       prev = __switch_to(prev,next);                                  \
+} while (0)
+
+extern void account_vtime(struct task_struct *, struct task_struct *);
+extern void account_tick_vtime(struct task_struct *);
+
+#define finish_arch_switch(prev) do {                                       \
+       set_fs(current->thread.mm_segment);                                  \
+       account_vtime(prev, current);                                        \
+} while (0)
+
+#endif /* __ASM_SWITCH_TO_H */
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
deleted file mode 100644 (file)
index 2e0bb7f..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright IBM Corp. 1999, 2009
- *
- * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
- */
-
-#ifndef __ASM_SYSTEM_H
-#define __ASM_SYSTEM_H
-
-#include <linux/preempt.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <asm/types.h>
-#include <asm/ptrace.h>
-#include <asm/setup.h>
-#include <asm/processor.h>
-#include <asm/lowcore.h>
-#include <asm/cmpxchg.h>
-
-#ifdef __KERNEL__
-
-struct task_struct;
-
-extern struct task_struct *__switch_to(void *, void *);
-extern void update_per_regs(struct task_struct *task);
-
-static inline void save_fp_regs(s390_fp_regs *fpregs)
-{
-       asm volatile(
-               "       std     0,%O0+8(%R0)\n"
-               "       std     2,%O0+24(%R0)\n"
-               "       std     4,%O0+40(%R0)\n"
-               "       std     6,%O0+56(%R0)"
-               : "=Q" (*fpregs) : "Q" (*fpregs));
-       if (!MACHINE_HAS_IEEE)
-               return;
-       asm volatile(
-               "       stfpc   %0\n"
-               "       std     1,%O0+16(%R0)\n"
-               "       std     3,%O0+32(%R0)\n"
-               "       std     5,%O0+48(%R0)\n"
-               "       std     7,%O0+64(%R0)\n"
-               "       std     8,%O0+72(%R0)\n"
-               "       std     9,%O0+80(%R0)\n"
-               "       std     10,%O0+88(%R0)\n"
-               "       std     11,%O0+96(%R0)\n"
-               "       std     12,%O0+104(%R0)\n"
-               "       std     13,%O0+112(%R0)\n"
-               "       std     14,%O0+120(%R0)\n"
-               "       std     15,%O0+128(%R0)\n"
-               : "=Q" (*fpregs) : "Q" (*fpregs));
-}
-
-static inline void restore_fp_regs(s390_fp_regs *fpregs)
-{
-       asm volatile(
-               "       ld      0,%O0+8(%R0)\n"
-               "       ld      2,%O0+24(%R0)\n"
-               "       ld      4,%O0+40(%R0)\n"
-               "       ld      6,%O0+56(%R0)"
-               : : "Q" (*fpregs));
-       if (!MACHINE_HAS_IEEE)
-               return;
-       asm volatile(
-               "       lfpc    %0\n"
-               "       ld      1,%O0+16(%R0)\n"
-               "       ld      3,%O0+32(%R0)\n"
-               "       ld      5,%O0+48(%R0)\n"
-               "       ld      7,%O0+64(%R0)\n"
-               "       ld      8,%O0+72(%R0)\n"
-               "       ld      9,%O0+80(%R0)\n"
-               "       ld      10,%O0+88(%R0)\n"
-               "       ld      11,%O0+96(%R0)\n"
-               "       ld      12,%O0+104(%R0)\n"
-               "       ld      13,%O0+112(%R0)\n"
-               "       ld      14,%O0+120(%R0)\n"
-               "       ld      15,%O0+128(%R0)\n"
-               : : "Q" (*fpregs));
-}
-
-static inline void save_access_regs(unsigned int *acrs)
-{
-       asm volatile("stam 0,15,%0" : "=Q" (*acrs));
-}
-
-static inline void restore_access_regs(unsigned int *acrs)
-{
-       asm volatile("lam 0,15,%0" : : "Q" (*acrs));
-}
-
-#define switch_to(prev,next,last) do {                                 \
-       if (prev->mm) {                                                 \
-               save_fp_regs(&prev->thread.fp_regs);                    \
-               save_access_regs(&prev->thread.acrs[0]);                \
-       }                                                               \
-       if (next->mm) {                                                 \
-               restore_fp_regs(&next->thread.fp_regs);                 \
-               restore_access_regs(&next->thread.acrs[0]);             \
-               update_per_regs(next);                                  \
-       }                                                               \
-       prev = __switch_to(prev,next);                                  \
-} while (0)
-
-extern void account_vtime(struct task_struct *, struct task_struct *);
-extern void account_tick_vtime(struct task_struct *);
-
-#ifdef CONFIG_PFAULT
-extern int pfault_init(void);
-extern void pfault_fini(void);
-#else /* CONFIG_PFAULT */
-#define pfault_init()          ({-1;})
-#define pfault_fini()          do { } while (0)
-#endif /* CONFIG_PFAULT */
-
-extern void cmma_init(void);
-extern int memcpy_real(void *, void *, size_t);
-extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
-extern int copy_to_user_real(void __user *dest, void *src, size_t count);
-extern int copy_from_user_real(void *dest, void __user *src, size_t count);
-
-#define finish_arch_switch(prev) do {                                       \
-       set_fs(current->thread.mm_segment);                                  \
-       account_vtime(prev, current);                                        \
-} while (0)
-
-#define nop() asm volatile("nop")
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * This is very similar to the ppc eieio/sync instruction in that is
- * does a checkpoint syncronisation & makes sure that 
- * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
- */
-
-#define eieio()        asm volatile("bcr 15,0" : : : "memory")
-#define SYNC_OTHER_CORES(x)   eieio()
-#define mb()    eieio()
-#define rmb()   eieio()
-#define wmb()   eieio()
-#define read_barrier_depends() do { } while(0)
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()    read_barrier_depends()
-#define smp_mb__before_clear_bit()     smp_mb()
-#define smp_mb__after_clear_bit()      smp_mb()
-
-
-#define set_mb(var, value)      do { var = value; mb(); } while (0)
-
-#ifdef __s390x__
-
-#define __ctl_load(array, low, high) ({                                \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       lctlg   %1,%2,%0\n"                     \
-               : : "Q" (*(addrtype *)(&array)),                \
-                   "i" (low), "i" (high));                     \
-       })
-
-#define __ctl_store(array, low, high) ({                       \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       stctg   %1,%2,%0\n"                     \
-               : "=Q" (*(addrtype *)(&array))                  \
-               : "i" (low), "i" (high));                       \
-       })
-
-#else /* __s390x__ */
-
-#define __ctl_load(array, low, high) ({                                \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       lctl    %1,%2,%0\n"                     \
-               : : "Q" (*(addrtype *)(&array)),                \
-                   "i" (low), "i" (high));                     \
-})
-
-#define __ctl_store(array, low, high) ({                       \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       stctl   %1,%2,%0\n"                     \
-               : "=Q" (*(addrtype *)(&array))                  \
-               : "i" (low), "i" (high));                       \
-       })
-
-#endif /* __s390x__ */
-
-#define __ctl_set_bit(cr, bit) ({      \
-       unsigned long __dummy;          \
-       __ctl_store(__dummy, cr, cr);   \
-       __dummy |= 1UL << (bit);        \
-       __ctl_load(__dummy, cr, cr);    \
-})
-
-#define __ctl_clear_bit(cr, bit) ({    \
-       unsigned long __dummy;          \
-       __ctl_store(__dummy, cr, cr);   \
-       __dummy &= ~(1UL << (bit));     \
-       __ctl_load(__dummy, cr, cr);    \
-})
-
-/*
- * Use to set psw mask except for the first byte which
- * won't be changed by this function.
- */
-static inline void
-__set_psw_mask(unsigned long mask)
-{
-       __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
-}
-
-#define local_mcck_enable() \
-       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
-#define local_mcck_disable() \
-       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
-
-#ifdef CONFIG_SMP
-
-extern void smp_ctl_set_bit(int cr, int bit);
-extern void smp_ctl_clear_bit(int cr, int bit);
-#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
-#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
-
-#else
-
-#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
-#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
-
-#endif /* CONFIG_SMP */
-
-#define MAX_FACILITY_BIT (256*8)       /* stfle_fac_list has 256 bytes */
-
-/*
- * The test_facility function uses the bit odering where the MSB is bit 0.
- * That makes it easier to query facility bits with the bit number as
- * documented in the Principles of Operation.
- */
-static inline int test_facility(unsigned long nr)
-{
-       unsigned char *ptr;
-
-       if (nr >= MAX_FACILITY_BIT)
-               return 0;
-       ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3);
-       return (*ptr & (0x80 >> (nr & 7))) != 0;
-}
-
-/**
- * stfle - Store facility list extended
- * @stfle_fac_list: array where facility list can be stored
- * @size: size of passed in array in double words
- */
-static inline void stfle(u64 *stfle_fac_list, int size)
-{
-       unsigned long nr;
-
-       preempt_disable();
-       S390_lowcore.stfl_fac_list = 0;
-       asm volatile(
-               "       .insn s,0xb2b10000,0(0)\n" /* stfl */
-               "0:\n"
-               EX_TABLE(0b, 0b)
-               : "=m" (S390_lowcore.stfl_fac_list));
-       nr = 4; /* bytes stored by stfl */
-       memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
-       if (S390_lowcore.stfl_fac_list & 0x01000000) {
-               /* More facility bits available with stfle */
-               register unsigned long reg0 asm("0") = size - 1;
-
-               asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
-                            : "+d" (reg0)
-                            : "a" (stfle_fac_list)
-                            : "memory", "cc");
-               nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
-       }
-       memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
-       preempt_enable();
-}
-
-static inline unsigned short stap(void)
-{
-       unsigned short cpu_address;
-
-       asm volatile("stap %0" : "=m" (cpu_address));
-       return cpu_address;
-}
-
-extern void (*_machine_restart)(char *command);
-extern void (*_machine_halt)(void);
-extern void (*_machine_power_off)(void);
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-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;
-}
-
-#endif /* __KERNEL__ */
-
-#endif
index 2b23885e81e9a40019cc0d0e03748f3d4bbf670e..8f2cada4f7c916d9d88fb87cbb390cf99e4b793e 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <asm/ctl_reg.h>
 
 #define VERIFY_READ     0
 #define VERIFY_WRITE    1
@@ -375,4 +376,9 @@ clear_user(void __user *to, unsigned long n)
        return n;
 }
 
+extern int memcpy_real(void *, void *, size_t);
+extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
+extern int copy_to_user_real(void __user *dest, void *src, size_t count);
+extern int copy_from_user_real(void *dest, void __user *src, size_t count);
+
 #endif /* __S390_UACCESS_H */
index ed8c913db79eb6db214100cf31fe57ffbc11a39a..83e6edf5cf17345d592636a49229394777600c82 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/timer.h>
 #include <asm/vdso.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 /*
  * Make sure that the compiler is new enough. We want a compiler that
index 53a82c8d50e9cd057bda361e082ddf453066de7f..28040fd5e8a2232f39893545938590aaffa20315 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include <asm/switch_to.h>
 #include "compat_linux.h"
 #include "compat_ptrace.h"
 #include "entry.h"
index 3e8b8816f309937c6ac5b2af395c346f98e19bb2..e3dd886e1b3218e6b59ec29af4426879b6279570 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <asm/ebcdic.h>
 #include <asm/cpcmd.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 static DEFINE_SPINLOCK(cpcmd_lock);
index e2f847599c8e1d76064147345126684b040f5311..3221c6fca8bb77ceedd9c6ee00b9c2018d45251d 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 578eb4e6d1577ebcbe641533481bfdc2101e6832..9475e682727f8ed3915e016db277c5d80bf9996c 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/sysinfo.h>
 #include <asm/cpcmd.h>
 #include <asm/sclp.h>
-#include <asm/system.h>
+#include <asm/facility.h>
 #include "entry.h"
 
 /*
index 8431b92ca3ae8d3cf58e837f0fe4cf49d7038288..ac39e7a731fc47542e7e36bc81ae557b1dddaf98 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/slab.h>
 #include <asm/sysinfo.h>
 #include <asm/ebcdic.h>
-#include <asm/system.h>
 #include <asm/debug.h>
 #include <asm/ipl.h>
 
index 0f8cdf1268d038715483ae5d81dfa8df2080ad25..bdad47d544783d89fa015ee6db34d52a2a555695 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/reset.h>
 #include <asm/ipl.h>
index bbe522672e063526e327ebd6a86d51f17e73812d..e8d6c214d498a0aaf5037f7d64c5fd7e6306fbc9 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <asm/checksum.h>
 #include <asm/lowcore.h>
-#include <asm/system.h>
 #include <asm/os_info.h>
 
 /*
index 3732e4c09cbe5c68e1a8fb1894a3b897fae9f0f7..60055cefdd04da2db1d3af3061d80eb50f669e17 100644 (file)
 #include <linux/kprobes.h>
 #include <linux/random.h>
 #include <linux/module.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/timer.h>
 #include <asm/nmi.h>
 #include <asm/smp.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
index 61f95489d70c2539068a6cfc2dc3acc55d4a3cac..02f300fbf070ac5abbfe667023237ca0a45f6fcf 100644 (file)
@@ -26,9 +26,9 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 #ifdef CONFIG_COMPAT
index 38e751278bf75680fcc5320f51c3cf7f4fd1f878..1581ea2e027a02edd69000d1edd9cd98b29730d2 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <asm/ipl.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/mmu_context.h>
 #include <asm/cpcmd.h>
index f29f5ef400e5bff466339e26b9a2fc3de5a9c630..f7582b27f600af4014d780e51a314f06e36041f4 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
index 47df775c844d48aa69c648fb17b488186beab8e7..aa1494d0e380f907f56c74e53198dcad2dff592d 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/mm.h>
-#include <asm/system.h>
+#include <asm/ctl_reg.h>
 
 /*
  * References to section boundaries
index cd6ebe12c481065c19822b42dd647f70a9d021d9..77cdf4234ebc8bd7e62bf0c2893147953e4dc9dd 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kprobes.h>
 #include <linux/bug.h>
 #include <linux/utsname.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 9c80138206b079dc79e61b88d489c56148f47bad..ea5590fdca3bb8266caa0e25410dd744b103b4c9 100644 (file)
 #include <linux/compat.h>
 #include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
 #include <asm/vdso.h>
+#include <asm/facility.h>
 
 #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
 extern char vdso32_start, vdso32_end;
index a21634173a6612f4491c884a989c7673c9958138..78eb9847008f2cc8eff307a89e330d42b3dcd69a 100644 (file)
@@ -34,6 +34,15 @@ config KVM
 
          If unsure, say N.
 
+config KVM_S390_UCONTROL
+       bool "Userspace controlled virtual machines"
+       depends on KVM
+       ---help---
+         Allow CAP_SYS_ADMIN users to create KVM virtual machines that are
+         controlled by userspace.
+
+         If unsure, say N.
+
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
 source drivers/vhost/Kconfig
index 8943e82cd4d94248ef8708839d6c7e0d99e324f9..a353f0ea45c2235d73455ab9013fbfeb1409223b 100644 (file)
@@ -20,8 +20,8 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)
        unsigned long start, end;
        unsigned long prefix  = vcpu->arch.sie_block->prefix;
 
-       start = vcpu->arch.guest_gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
-       end = vcpu->arch.guest_gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+       start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
+       end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
 
        if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
            || start < 2 * PAGE_SIZE)
@@ -56,7 +56,7 @@ static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
 static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
 {
        unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
-       unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff;
+       unsigned long subcode = vcpu->run->s.regs.gprs[reg] & 0xffff;
 
        VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
        switch (subcode) {
index 02434543eabbede6e5e2fbc17f8e649f5a19871a..361456577c6f0f537721cb4eb2bcccb8115026a3 100644 (file)
@@ -36,7 +36,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
 
        useraddr = disp2;
        if (base2)
-               useraddr += vcpu->arch.guest_gprs[base2];
+               useraddr += vcpu->run->s.regs.gprs[base2];
 
        if (useraddr & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -75,7 +75,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
 
        useraddr = disp2;
        if (base2)
-               useraddr += vcpu->arch.guest_gprs[base2];
+               useraddr += vcpu->run->s.regs.gprs[base2];
 
        if (useraddr & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -133,13 +133,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
 
        vcpu->stat.exit_stop_request++;
        spin_lock_bh(&vcpu->arch.local_int.lock);
-       if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
-               vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
-               rc = kvm_s390_vcpu_store_status(vcpu,
-                                                 KVM_S390_STORE_STATUS_NOADDR);
-               if (rc >= 0)
-                       rc = -EOPNOTSUPP;
-       }
 
        if (vcpu->arch.local_int.action_bits & ACTION_RELOADVCPU_ON_STOP) {
                vcpu->arch.local_int.action_bits &= ~ACTION_RELOADVCPU_ON_STOP;
@@ -155,7 +148,18 @@ static int handle_stop(struct kvm_vcpu *vcpu)
                rc = -EOPNOTSUPP;
        }
 
-       spin_unlock_bh(&vcpu->arch.local_int.lock);
+       if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
+               vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
+               /* store status must be called unlocked. Since local_int.lock
+                * only protects local_int.* and not guest memory we can give
+                * up the lock here */
+               spin_unlock_bh(&vcpu->arch.local_int.lock);
+               rc = kvm_s390_vcpu_store_status(vcpu,
+                                               KVM_S390_STORE_STATUS_NOADDR);
+               if (rc >= 0)
+                       rc = -EOPNOTSUPP;
+       } else
+               spin_unlock_bh(&vcpu->arch.local_int.lock);
        return rc;
 }
 
index f0647ce6da21db24bb926afe148f8f3bc828fcf2..2d9f9a72bb8108ddb3ea4c03c3339eb0d3f5d118 100644 (file)
@@ -236,8 +236,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
                VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
                           inti->prefix.address);
                vcpu->stat.deliver_prefix_signal++;
-               vcpu->arch.sie_block->prefix = inti->prefix.address;
-               vcpu->arch.sie_block->ihcpu = 0xffff;
+               kvm_s390_set_prefix(vcpu, inti->prefix.address);
                break;
 
        case KVM_S390_RESTART:
index d1c445732451b6d1bd1c4b95db3d6467ff629c68..217ce44395a4e7978194a7c9cc042bad1f84e889 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/lowcore.h>
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
-#include <asm/system.h>
+#include <asm/switch_to.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -129,6 +129,10 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_S390_PSW:
        case KVM_CAP_S390_GMAP:
        case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_S390_UCONTROL
+       case KVM_CAP_S390_UCONTROL:
+#endif
+       case KVM_CAP_SYNC_REGS:
                r = 1;
                break;
        default:
@@ -171,11 +175,22 @@ long kvm_arch_vm_ioctl(struct file *filp,
        return r;
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        int rc;
        char debug_name[16];
 
+       rc = -EINVAL;
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if (type & ~KVM_VM_S390_UCONTROL)
+               goto out_err;
+       if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
+               goto out_err;
+#else
+       if (type)
+               goto out_err;
+#endif
+
        rc = s390_enable_sie();
        if (rc)
                goto out_err;
@@ -198,10 +213,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
        debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
        VM_EVENT(kvm, 3, "%s", "vm created");
 
-       kvm->arch.gmap = gmap_alloc(current->mm);
-       if (!kvm->arch.gmap)
-               goto out_nogmap;
-
+       if (type & KVM_VM_S390_UCONTROL) {
+               kvm->arch.gmap = NULL;
+       } else {
+               kvm->arch.gmap = gmap_alloc(current->mm);
+               if (!kvm->arch.gmap)
+                       goto out_nogmap;
+       }
        return 0;
 out_nogmap:
        debug_unregister(kvm->arch.dbf);
@@ -214,11 +232,18 @@ out_err:
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        VCPU_EVENT(vcpu, 3, "%s", "free cpu");
-       clear_bit(63 - vcpu->vcpu_id, (unsigned long *) &vcpu->kvm->arch.sca->mcn);
-       if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
-               (__u64) vcpu->arch.sie_block)
-               vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+       if (!kvm_is_ucontrol(vcpu->kvm)) {
+               clear_bit(63 - vcpu->vcpu_id,
+                         (unsigned long *) &vcpu->kvm->arch.sca->mcn);
+               if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
+                   (__u64) vcpu->arch.sie_block)
+                       vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+       }
        smp_mb();
+
+       if (kvm_is_ucontrol(vcpu->kvm))
+               gmap_free(vcpu->arch.gmap);
+
        free_page((unsigned long)(vcpu->arch.sie_block));
        kvm_vcpu_uninit(vcpu);
        kfree(vcpu);
@@ -249,13 +274,25 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        kvm_free_vcpus(kvm);
        free_page((unsigned long)(kvm->arch.sca));
        debug_unregister(kvm->arch.dbf);
-       gmap_free(kvm->arch.gmap);
+       if (!kvm_is_ucontrol(kvm))
+               gmap_free(kvm->arch.gmap);
 }
 
 /* Section: vcpu related */
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+       if (kvm_is_ucontrol(vcpu->kvm)) {
+               vcpu->arch.gmap = gmap_alloc(current->mm);
+               if (!vcpu->arch.gmap)
+                       return -ENOMEM;
+               return 0;
+       }
+
        vcpu->arch.gmap = vcpu->kvm->arch.gmap;
+       vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
+                                   KVM_SYNC_GPRS |
+                                   KVM_SYNC_ACRS |
+                                   KVM_SYNC_CRS;
        return 0;
 }
 
@@ -270,7 +307,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        save_access_regs(vcpu->arch.host_acrs);
        vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
        restore_fp_regs(&vcpu->arch.guest_fpregs);
-       restore_access_regs(vcpu->arch.guest_acrs);
+       restore_access_regs(vcpu->run->s.regs.acrs);
        gmap_enable(vcpu->arch.gmap);
        atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 }
@@ -280,7 +317,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
        atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
        save_fp_regs(&vcpu->arch.guest_fpregs);
-       save_access_regs(vcpu->arch.guest_acrs);
+       save_access_regs(vcpu->run->s.regs.acrs);
        restore_fp_regs(&vcpu->arch.host_fpregs);
        restore_access_regs(vcpu->arch.host_acrs);
 }
@@ -290,8 +327,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
        /* this equals initial cpu reset in pop, but we don't switch to ESA */
        vcpu->arch.sie_block->gpsw.mask = 0UL;
        vcpu->arch.sie_block->gpsw.addr = 0UL;
-       vcpu->arch.sie_block->prefix    = 0UL;
-       vcpu->arch.sie_block->ihcpu     = 0xffff;
+       kvm_s390_set_prefix(vcpu, 0);
        vcpu->arch.sie_block->cputm     = 0UL;
        vcpu->arch.sie_block->ckc       = 0UL;
        vcpu->arch.sie_block->todpr     = 0;
@@ -342,12 +378,19 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
                goto out_free_cpu;
 
        vcpu->arch.sie_block->icpua = id;
-       BUG_ON(!kvm->arch.sca);
-       if (!kvm->arch.sca->cpu[id].sda)
-               kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
-       vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
-       vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
-       set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
+       if (!kvm_is_ucontrol(kvm)) {
+               if (!kvm->arch.sca) {
+                       WARN_ON_ONCE(1);
+                       goto out_free_cpu;
+               }
+               if (!kvm->arch.sca->cpu[id].sda)
+                       kvm->arch.sca->cpu[id].sda =
+                               (__u64) vcpu->arch.sie_block;
+               vcpu->arch.sie_block->scaoh =
+                       (__u32)(((__u64)kvm->arch.sca) >> 32);
+               vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
+               set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
+       }
 
        spin_lock_init(&vcpu->arch.local_int.lock);
        INIT_LIST_HEAD(&vcpu->arch.local_int.list);
@@ -388,29 +431,29 @@ static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
-       memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
+       memcpy(&vcpu->run->s.regs.gprs, &regs->gprs, sizeof(regs->gprs));
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
-       memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
+       memcpy(&regs->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs));
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
-       memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
+       memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs));
        memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
-       restore_access_regs(vcpu->arch.guest_acrs);
+       restore_access_regs(vcpu->run->s.regs.acrs);
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
-       memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
+       memcpy(&sregs->acrs, &vcpu->run->s.regs.acrs, sizeof(sregs->acrs));
        memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
        return 0;
 }
@@ -418,7 +461,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
-       vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+       vcpu->arch.guest_fpregs.fpc = fpu->fpc & FPC_VALID_MASK;
        restore_fp_regs(&vcpu->arch.guest_fpregs);
        return 0;
 }
@@ -467,9 +510,11 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
        return -EINVAL; /* not implemented yet */
 }
 
-static void __vcpu_run(struct kvm_vcpu *vcpu)
+static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
-       memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
+       int rc;
+
+       memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16);
 
        if (need_resched())
                schedule();
@@ -477,7 +522,8 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        if (test_thread_flag(TIF_MCCK_PENDING))
                s390_handle_mcck();
 
-       kvm_s390_deliver_pending_interrupts(vcpu);
+       if (!kvm_is_ucontrol(vcpu->kvm))
+               kvm_s390_deliver_pending_interrupts(vcpu);
 
        vcpu->arch.sie_block->icptcode = 0;
        local_irq_disable();
@@ -485,9 +531,15 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        local_irq_enable();
        VCPU_EVENT(vcpu, 6, "entering sie flags %x",
                   atomic_read(&vcpu->arch.sie_block->cpuflags));
-       if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
-               VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
-               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+       rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
+       if (rc) {
+               if (kvm_is_ucontrol(vcpu->kvm)) {
+                       rc = SIE_INTERCEPT_UCONTROL;
+               } else {
+                       VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
+                       kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+                       rc = 0;
+               }
        }
        VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
                   vcpu->arch.sie_block->icptcode);
@@ -495,7 +547,8 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        kvm_guest_exit();
        local_irq_enable();
 
-       memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
+       memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
+       return rc;
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -516,6 +569,7 @@ rerun_vcpu:
        case KVM_EXIT_UNKNOWN:
        case KVM_EXIT_INTR:
        case KVM_EXIT_S390_RESET:
+       case KVM_EXIT_S390_UCONTROL:
                break;
        default:
                BUG();
@@ -523,12 +577,26 @@ rerun_vcpu:
 
        vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
        vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX) {
+               kvm_run->kvm_dirty_regs &= ~KVM_SYNC_PREFIX;
+               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+       }
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
+               kvm_run->kvm_dirty_regs &= ~KVM_SYNC_CRS;
+               memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
+               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+       }
 
        might_fault();
 
        do {
-               __vcpu_run(vcpu);
-               rc = kvm_handle_sie_intercept(vcpu);
+               rc = __vcpu_run(vcpu);
+               if (rc)
+                       break;
+               if (kvm_is_ucontrol(vcpu->kvm))
+                       rc = -EOPNOTSUPP;
+               else
+                       rc = kvm_handle_sie_intercept(vcpu);
        } while (!signal_pending(current) && !rc);
 
        if (rc == SIE_INTERCEPT_RERUNVCPU)
@@ -539,6 +607,16 @@ rerun_vcpu:
                rc = -EINTR;
        }
 
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if (rc == SIE_INTERCEPT_UCONTROL) {
+               kvm_run->exit_reason = KVM_EXIT_S390_UCONTROL;
+               kvm_run->s390_ucontrol.trans_exc_code =
+                       current->thread.gmap_addr;
+               kvm_run->s390_ucontrol.pgm_code = 0x10;
+               rc = 0;
+       }
+#endif
+
        if (rc == -EOPNOTSUPP) {
                /* intercept cannot be handled in-kernel, prepare kvm-run */
                kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
@@ -556,6 +634,8 @@ rerun_vcpu:
 
        kvm_run->psw_mask     = vcpu->arch.sie_block->gpsw.mask;
        kvm_run->psw_addr     = vcpu->arch.sie_block->gpsw.addr;
+       kvm_run->s.regs.prefix = vcpu->arch.sie_block->prefix;
+       memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
 
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
@@ -602,7 +682,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
                return -EFAULT;
 
        if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
-                       vcpu->arch.guest_gprs, 128, prefix))
+                       vcpu->run->s.regs.gprs, 128, prefix))
                return -EFAULT;
 
        if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
@@ -631,7 +711,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
                return -EFAULT;
 
        if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
-                       &vcpu->arch.guest_acrs, 64, prefix))
+                       &vcpu->run->s.regs.acrs, 64, prefix))
                return -EFAULT;
 
        if (__guestcopy(vcpu,
@@ -673,12 +753,77 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        case KVM_S390_INITIAL_RESET:
                r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
                break;
+#ifdef CONFIG_KVM_S390_UCONTROL
+       case KVM_S390_UCAS_MAP: {
+               struct kvm_s390_ucas_mapping ucasmap;
+
+               if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (!kvm_is_ucontrol(vcpu->kvm)) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
+                                    ucasmap.vcpu_addr, ucasmap.length);
+               break;
+       }
+       case KVM_S390_UCAS_UNMAP: {
+               struct kvm_s390_ucas_mapping ucasmap;
+
+               if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (!kvm_is_ucontrol(vcpu->kvm)) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
+                       ucasmap.length);
+               break;
+       }
+#endif
+       case KVM_S390_VCPU_FAULT: {
+               r = gmap_fault(arg, vcpu->arch.gmap);
+               if (!IS_ERR_VALUE(r))
+                       r = 0;
+               break;
+       }
        default:
-               r = -EINVAL;
+               r = -ENOTTY;
        }
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
+                && (kvm_is_ucontrol(vcpu->kvm))) {
+               vmf->page = virt_to_page(vcpu->arch.sie_block);
+               get_page(vmf->page);
+               return 0;
+       }
+#endif
+       return VM_FAULT_SIGBUS;
+}
+
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
 /* Section: memory related */
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                   struct kvm_memory_slot *memslot,
index 99b0b7597115e023396953e7748f260d8d469091..ff28f9d1c9eb94a2f50c2775ddf35cfbd3573a54 100644 (file)
@@ -26,6 +26,7 @@ typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
 
 /* negativ values are error codes, positive values for internal conditions */
 #define SIE_INTERCEPT_RERUNVCPU                (1<<0)
+#define SIE_INTERCEPT_UCONTROL         (1<<1)
 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
 
 #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
@@ -47,6 +48,23 @@ static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
        return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
 }
 
+static inline int kvm_is_ucontrol(struct kvm *kvm)
+{
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if (kvm->arch.gmap)
+               return 0;
+       return 1;
+#else
+       return 0;
+#endif
+}
+
+static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
+{
+       vcpu->arch.sie_block->prefix = prefix & 0x7fffe000u;
+       vcpu->arch.sie_block->ihcpu  = 0xffff;
+}
+
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
 void kvm_s390_tasklet(unsigned long parm);
index d02638959922aba41712d16d6dfb20f86f87ec8b..e5a45dbd26ac58e98cdf48b198128e067ef66e31 100644 (file)
@@ -33,7 +33,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
 
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        /* must be word boundary */
        if (operand2 & 3) {
@@ -56,8 +56,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
                goto out;
        }
 
-       vcpu->arch.sie_block->prefix = address;
-       vcpu->arch.sie_block->ihcpu = 0xffff;
+       kvm_s390_set_prefix(vcpu, address);
 
        VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
 out:
@@ -74,7 +73,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
        vcpu->stat.instruction_stpx++;
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        /* must be word boundary */
        if (operand2 & 3) {
@@ -106,7 +105,7 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
        vcpu->stat.instruction_stap++;
        useraddr = disp2;
        if (base2)
-               useraddr += vcpu->arch.guest_gprs[base2];
+               useraddr += vcpu->run->s.regs.gprs[base2];
 
        if (useraddr & 1) {
                kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -181,7 +180,7 @@ static int handle_stidp(struct kvm_vcpu *vcpu)
        vcpu->stat.instruction_stidp++;
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        if (operand2 & 7) {
                kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -232,9 +231,9 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
 
 static int handle_stsi(struct kvm_vcpu *vcpu)
 {
-       int fc = (vcpu->arch.guest_gprs[0] & 0xf0000000) >> 28;
-       int sel1 = vcpu->arch.guest_gprs[0] & 0xff;
-       int sel2 = vcpu->arch.guest_gprs[1] & 0xffff;
+       int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
+       int sel1 = vcpu->run->s.regs.gprs[0] & 0xff;
+       int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff;
        int base2 = vcpu->arch.sie_block->ipb >> 28;
        int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
        u64 operand2;
@@ -245,14 +244,14 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        if (operand2 & 0xfff && fc > 0)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
        switch (fc) {
        case 0:
-               vcpu->arch.guest_gprs[0] = 3 << 28;
+               vcpu->run->s.regs.gprs[0] = 3 << 28;
                vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
                return 0;
        case 1: /* same handling for 1 and 2 */
@@ -281,7 +280,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
        }
        free_page(mem);
        vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
-       vcpu->arch.guest_gprs[0] = 0;
+       vcpu->run->s.regs.gprs[0] = 0;
        return 0;
 out_mem:
        free_page(mem);
@@ -333,8 +332,8 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
        int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
        int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
        int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
-       u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
-       u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
+       u64 address1 = disp1 + base1 ? vcpu->run->s.regs.gprs[base1] : 0;
+       u64 address2 = disp2 + base2 ? vcpu->run->s.regs.gprs[base2] : 0;
        struct vm_area_struct *vma;
        unsigned long user_address;
 
index 0a7941d74bc68b30b9121090aeb96111c86058b7..0ad4cf238391d5889b8d3ea955c116edd6a80a36 100644 (file)
@@ -48,7 +48,7 @@
 
 
 static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
-                       unsigned long *reg)
+                       u64 *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        int rc;
@@ -160,12 +160,15 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
        inti->type = KVM_S390_SIGP_STOP;
 
        spin_lock_bh(&li->lock);
+       if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED))
+               goto out;
        list_add_tail(&inti->list, &li->list);
        atomic_set(&li->active, 1);
        atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
        li->action_bits |= action;
        if (waitqueue_active(&li->wq))
                wake_up_interruptible(&li->wq);
+out:
        spin_unlock_bh(&li->lock);
 
        return 0; /* order accepted */
@@ -220,7 +223,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
 }
 
 static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
-                            unsigned long *reg)
+                            u64 *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        struct kvm_s390_local_interrupt *li = NULL;
@@ -278,7 +281,7 @@ out_fi:
 }
 
 static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
-                               unsigned long *reg)
+                               u64 *reg)
 {
        int rc;
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
@@ -309,6 +312,34 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
        return rc;
 }
 
+static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
+       int rc = 0;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct kvm_s390_local_interrupt *li;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       spin_lock(&fi->lock);
+       li = fi->local_int[cpu_addr];
+       if (li == NULL) {
+               rc = 3; /* not operational */
+               goto out;
+       }
+
+       spin_lock_bh(&li->lock);
+       if (li->action_bits & ACTION_STOP_ON_STOP)
+               rc = 2; /* busy */
+       else
+               VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
+                       cpu_addr);
+       spin_unlock_bh(&li->lock);
+out:
+       spin_unlock(&fi->lock);
+       return rc;
+}
+
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 {
        int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -316,7 +347,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
        int base2 = vcpu->arch.sie_block->ipb >> 28;
        int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
        u32 parameter;
-       u16 cpu_addr = vcpu->arch.guest_gprs[r3];
+       u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
        u8 order_code;
        int rc;
 
@@ -327,18 +358,18 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 
        order_code = disp2;
        if (base2)
-               order_code += vcpu->arch.guest_gprs[base2];
+               order_code += vcpu->run->s.regs.gprs[base2];
 
        if (r1 % 2)
-               parameter = vcpu->arch.guest_gprs[r1];
+               parameter = vcpu->run->s.regs.gprs[r1];
        else
-               parameter = vcpu->arch.guest_gprs[r1 + 1];
+               parameter = vcpu->run->s.regs.gprs[r1 + 1];
 
        switch (order_code) {
        case SIGP_SENSE:
                vcpu->stat.instruction_sigp_sense++;
                rc = __sigp_sense(vcpu, cpu_addr,
-                                 &vcpu->arch.guest_gprs[r1]);
+                                 &vcpu->run->s.regs.gprs[r1]);
                break;
        case SIGP_EXTERNAL_CALL:
                vcpu->stat.instruction_sigp_external_call++;
@@ -354,7 +385,8 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                break;
        case SIGP_STOP_STORE_STATUS:
                vcpu->stat.instruction_sigp_stop++;
-               rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP);
+               rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP |
+                                                ACTION_STOP_ON_STOP);
                break;
        case SIGP_SET_ARCH:
                vcpu->stat.instruction_sigp_arch++;
@@ -363,15 +395,18 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
        case SIGP_SET_PREFIX:
                vcpu->stat.instruction_sigp_prefix++;
                rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
-                                      &vcpu->arch.guest_gprs[r1]);
+                                      &vcpu->run->s.regs.gprs[r1]);
                break;
        case SIGP_SENSE_RUNNING:
                vcpu->stat.instruction_sigp_sense_running++;
                rc = __sigp_sense_running(vcpu, cpu_addr,
-                                         &vcpu->arch.guest_gprs[r1]);
+                                         &vcpu->run->s.regs.gprs[r1]);
                break;
        case SIGP_RESTART:
                vcpu->stat.instruction_sigp_restart++;
+               rc = __sigp_restart(vcpu, cpu_addr);
+               if (rc == 2) /* busy */
+                       break;
                /* user space must know about restart */
        default:
                return -EOPNOTSUPP;
index b17c42df61c9f9b8ee29c8c452e42bc317fe8f25..46ef3fd0663b5c1dfca0ca3b0d175c7a5d4fe990 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/hugetlb.h>
 #include <asm/asm-offsets.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
+#include <asm/facility.h>
 #include "../kernel/entry.h"
 
 #ifndef CONFIG_64BIT
index 50236610de83cc0cb8d76ca34bbd2cd0f5c0e0aa..2bea0605856e85ac76e96c7e7c8dbb34ff6c94a5 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/export.h>
 #include <linux/gfp.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -38,6 +37,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/ctl_reg.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 
index 1cb8427bedfb3862ca4ac57e7d2064757a3db2e3..7bb15fcca75ea572362d02a6b2626836868be9ed 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/gfp.h>
-#include <asm/system.h>
+#include <asm/ctl_reg.h>
 
 /*
  * This function writes to kernel memory bypassing DAT and possible
index 51b0738e13d12ef21ae05b68aa4ccc17d2862c9a..373adf69b01c48ceebfa2808131326ba5c7188dc 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
index f097d516d8c5ab0555d5d393c9d34eb6b688fa1e..c6646de07bf455acb80c3c94674cdc61c535677c 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/semaphore.h>
 #include <linux/oom.h>
 #include <linux/oprofile.h>
+
+#include <asm/facility.h>
 #include <asm/cpu_mf.h>
 #include <asm/irq.h>
 
index 84eb8ddf9f3f0242b3ef242fb998f121b972da3d..edf33dbded1ebe16e81c375d80d983498b25fc22 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_SCORE_ATOMIC_H
 #define _ASM_SCORE_ATOMIC_H
 
+#include <asm/cmpxchg.h>
 #include <asm-generic/atomic.h>
 
 #endif /* _ASM_SCORE_ATOMIC_H */
diff --git a/arch/score/include/asm/barrier.h b/arch/score/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..0eacb64
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _ASM_SCORE_BARRIER_H
+#define _ASM_SCORE_BARRIER_H
+
+#define mb()           barrier()
+#define rmb()          barrier()
+#define wmb()          barrier()
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+
+#define read_barrier_depends()         do {} while (0)
+#define smp_read_barrier_depends()     do {} while (0)
+
+#define set_mb(var, value)             do {var = value; wmb(); } while (0)
+
+#endif /* _ASM_SCORE_BARRIER_H */
index 2763b050fca8de135b63a26088fa43a853aa16a9..a304096b1894375d94ebd7ced3decc512fe3a782 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_SCORE_BITOPS_H
 
 #include <asm/byteorder.h> /* swab32 */
-#include <asm/system.h> /* save_flags */
 
 /*
  * clear_bit() doesn't provide any barrier for the compiler.
index bb76a330bcf14d0d225f0243171d89e6c557ee0c..fd7164af1f047344075621e91946d81551aea154 100644 (file)
@@ -3,4 +3,15 @@
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+extern void __die(const char *, struct pt_regs *, const char *,
+       const char *, unsigned long) __attribute__((noreturn));
+extern void __die_if_kernel(const char *, struct pt_regs *, const char *,
+       const char *, unsigned long);
+
+#define die(msg, regs)                                                 \
+       __die(msg, regs, __FILE__ ":", __func__, __LINE__)
+#define die_if_kernel(msg, regs)                                       \
+       __die_if_kernel(msg, regs, __FILE__ ":", __func__, __LINE__)
+
 #endif /* _ASM_SCORE_BUG_H */
diff --git a/arch/score/include/asm/cmpxchg.h b/arch/score/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..f384839
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _ASM_SCORE_CMPXCHG_H
+#define _ASM_SCORE_CMPXCHG_H
+
+#include <linux/irqflags.h>
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+       unsigned long retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       *m = val;
+       local_irq_restore(flags);
+       return retval;
+}
+
+#define xchg(ptr, v)                                           \
+       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
+                                       (unsigned long)(v)))
+
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+                               unsigned long old, unsigned long new)
+{
+       unsigned long retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       if (retval == old)
+               *m = new;
+       local_irq_restore(flags);
+       return retval;
+}
+
+#define cmpxchg(ptr, o, n)                                     \
+       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
+                                       (unsigned long)(o),     \
+                                       (unsigned long)(n)))
+
+#define __HAVE_ARCH_CMPXCHG    1
+
+#include <asm-generic/cmpxchg-local.h>
+
+#endif /* _ASM_SCORE_CMPXCHG_H */
diff --git a/arch/score/include/asm/exec.h b/arch/score/include/asm/exec.h
new file mode 100644 (file)
index 0000000..f9f3cd5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_SCORE_EXEC_H
+#define _ASM_SCORE_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* _ASM_SCORE_EXEC_H */
diff --git a/arch/score/include/asm/switch_to.h b/arch/score/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..031756b
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _ASM_SCORE_SWITCH_TO_H
+#define _ASM_SCORE_SWITCH_TO_H
+
+extern void *resume(void *last, void *next, void *next_ti);
+
+#define switch_to(prev, next, last)                            \
+do {                                                           \
+       (last) = resume(prev, next, task_thread_info(next));    \
+} while (0)
+
+#define finish_arch_switch(prev)       do {} while (0)
+
+#endif /* _ASM_SCORE_SWITCH_TO_H */
diff --git a/arch/score/include/asm/system.h b/arch/score/include/asm/system.h
deleted file mode 100644 (file)
index 589d5c7..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _ASM_SCORE_SYSTEM_H
-#define _ASM_SCORE_SYSTEM_H
-
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-struct pt_regs;
-struct task_struct;
-
-extern void *resume(void *last, void *next, void *next_ti);
-
-#define switch_to(prev, next, last)                            \
-do {                                                           \
-       (last) = resume(prev, next, task_thread_info(next));    \
-} while (0)
-
-#define finish_arch_switch(prev)       do {} while (0)
-
-typedef void (*vi_handler_t)(void);
-extern unsigned long arch_align_stack(unsigned long sp);
-
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-#define set_mb(var, value)             do {var = value; wmb(); } while (0)
-
-#define __HAVE_ARCH_CMPXCHG    1
-
-#include <asm-generic/cmpxchg-local.h>
-
-#ifndef __ASSEMBLY__
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
-static inline
-unsigned long __xchg(volatile unsigned long *m, unsigned long val)
-{
-       unsigned long retval;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       retval = *m;
-       *m = val;
-       local_irq_restore(flags);
-       return retval;
-}
-
-#define xchg(ptr, v)                                           \
-       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
-                                       (unsigned long)(v)))
-
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                               unsigned long old, unsigned long new)
-{
-       unsigned long retval;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       retval = *m;
-       if (retval == old)
-               *m = new;
-       local_irq_restore(flags);
-       return retval;
-}
-
-#define cmpxchg(ptr, o, n)                                     \
-       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-                                       (unsigned long)(o),     \
-                                       (unsigned long)(n)))
-
-extern void __die(const char *, struct pt_regs *, const char *,
-       const char *, unsigned long) __attribute__((noreturn));
-extern void __die_if_kernel(const char *, struct pt_regs *, const char *,
-       const char *, unsigned long);
-
-#define die(msg, regs)                                                 \
-       __die(msg, regs, __FILE__ ":", __func__, __LINE__)
-#define die_if_kernel(msg, regs)                                       \
-       __die_if_kernel(msg, regs, __FILE__ ":", __func__, __LINE__)
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_SCORE_SYSTEM_H */
index 713fb58ca50724309d14f326c047bc4443df4772..b190eb17a75beb088f90a2b5eccdcbaf13c506b7 100644 (file)
@@ -22,7 +22,7 @@ config SUPERH
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
+       select MAY_HAVE_SPARSE_IRQ
        select IRQ_FORCED_THREADING
        select RTC_LIB
        select GENERIC_ATOMIC64
index 4fb00369f0e2ebde486ccb67b68897198a423b0d..9a8aff3396197ca097d0a3d34c61c71da31401b4 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <mach/microdev.h>
 
index 467d9415a32e5d9ae4c331e6569fc4b26b55bfdb..9f7c56609e535b27365cd24777491de4d9a70c67 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_ATOMIC_IRQ_H
 #define __ASM_SH_ATOMIC_IRQ_H
 
+#include <linux/irqflags.h>
+
 /*
  * To get proper branch prediction for the main line, we must branch
  * forward to code at the end of this object's .text section, then
index 63a27dbc952e76af102407de991774adf893ecee..37f2f4a55231f9c09854708b9f0b07c4f4ad2016 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
 
index 483effd65e004bfadbea95c0da0c96d28716db72..8bcc51af9367e98a1a01db70d78aee2534027326 100644 (file)
@@ -33,4 +33,6 @@
 #define AT_L1D_CACHESHAPE      35
 #define AT_L2_CACHESHAPE       36
 
+#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
+
 #endif /* __ASM_SH_AUXVEC_H */
diff --git a/arch/sh/include/asm/barrier.h b/arch/sh/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..72c103d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
+ * Copyright (C) 2002 Paul Mundt
+ */
+#ifndef __ASM_SH_BARRIER_H
+#define __ASM_SH_BARRIER_H
+
+#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
+#include <asm/cache_insns.h>
+#endif
+
+/*
+ * A brief note on ctrl_barrier(), the control register write barrier.
+ *
+ * Legacy SH cores typically require a sequence of 8 nops after
+ * modification of a control register in order for the changes to take
+ * effect. On newer cores (like the sh4a and sh5) this is accomplished
+ * with icbi.
+ *
+ * Also note that on sh4a in the icbi case we can forego a synco for the
+ * write barrier, as it's not necessary for control registers.
+ *
+ * Historically we have only done this type of barrier for the MMUCR, but
+ * it's also necessary for the CCR, so we make it generic here instead.
+ */
+#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
+#define mb()           __asm__ __volatile__ ("synco": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
+#define ctrl_barrier() __icbi(PAGE_OFFSET)
+#define read_barrier_depends() do { } while(0)
+#else
+#define mb()           __asm__ __volatile__ ("": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("": : :"memory")
+#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
+#define read_barrier_depends() do { } while(0)
+#endif
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+
+#endif /* __ASM_SH_BARRIER_H */
index 90fa3e48b4d60816baf66acfc3eb71105752639e..ea8706d94f08d31f04ec75ae21958369dae9866c 100644 (file)
@@ -7,7 +7,6 @@
 #error only <linux/bitops.h> can be included directly
 #endif
 
-#include <asm/system.h>
 /* For __swab32 */
 #include <asm/byteorder.h>
 
diff --git a/arch/sh/include/asm/bl_bit.h b/arch/sh/include/asm/bl_bit.h
new file mode 100644 (file)
index 0000000..45e6b9f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_BL_BIT_H
+#define __ASM_SH_BL_BIT_H
+
+#ifdef CONFIG_SUPERH32
+# include "bl_bit_32.h"
+#else
+# include "bl_bit_64.h"
+#endif
+
+#endif /* __ASM_SH_BL_BIT_H */
diff --git a/arch/sh/include/asm/bl_bit_32.h b/arch/sh/include/asm/bl_bit_32.h
new file mode 100644 (file)
index 0000000..fd21eee
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __ASM_SH_BL_BIT_32_H
+#define __ASM_SH_BL_BIT_32_H
+
+static inline void set_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "or     %2, %0\n\t"
+               "and    %3, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "r" (0x10000000), "r" (0xffffff0f)
+               : "memory"
+       );
+}
+
+static inline void clear_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "and    %2, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "1" (~0x10000000)
+               : "memory"
+       );
+}
+
+#endif /* __ASM_SH_BL_BIT_32_H */
diff --git a/arch/sh/include/asm/bl_bit_64.h b/arch/sh/include/asm/bl_bit_64.h
new file mode 100644 (file)
index 0000000..6cc8711
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_BL_BIT_64_H
+#define __ASM_SH_BL_BIT_64_H
+
+#include <asm/processor.h>
+
+#define SR_BL_LL       0x0000000010000000LL
+
+static inline void set_bl_bit(void)
+{
+       unsigned long long __dummy0, __dummy1 = SR_BL_LL;
+
+       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
+                            "or        %0, %1, %0\n\t"
+                            "putcon    %0, " __SR "\n\t"
+                            : "=&r" (__dummy0)
+                            : "r" (__dummy1));
+
+}
+
+static inline void clear_bl_bit(void)
+{
+       unsigned long long __dummy0, __dummy1 = ~SR_BL_LL;
+
+       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
+                            "and       %0, %1, %0\n\t"
+                            "putcon    %0, " __SR "\n\t"
+                            : "=&r" (__dummy0)
+                            : "r" (__dummy1));
+}
+
+#endif /* __ASM_SH_BL_BIT_64_H */
index 6323f864d1116ab2038074b7efa5d8282e5f0449..2b87d86bfc4169384ce529af620c5db9e5238acf 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
+#include <linux/linkage.h>
+
 #define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
 #define BUGFLAG_UNWINDER       (1 << 1)
 
@@ -107,4 +109,7 @@ do {                                                        \
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+
 #endif /* __ASM_SH_BUG_H */
diff --git a/arch/sh/include/asm/cache_insns.h b/arch/sh/include/asm/cache_insns.h
new file mode 100644 (file)
index 0000000..d25fbe5
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASM_SH_CACHE_INSNS_H
+#define __ASM_SH_CACHE_INSNS_H
+
+
+#ifdef CONFIG_SUPERH32
+# include "cache_insns_32.h"
+#else
+# include "cache_insns_64.h"
+#endif
+
+#endif /* __ASM_SH_CACHE_INSNS_H */
diff --git a/arch/sh/include/asm/cache_insns_32.h b/arch/sh/include/asm/cache_insns_32.h
new file mode 100644 (file)
index 0000000..b92fe54
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_CACHE_INSNS_32_H
+#define __ASM_SH_CACHE_INSNS_32_H
+
+#include <linux/types.h>
+
+#if defined(CONFIG_CPU_SH4A)
+#define __icbi(addr)   __asm__ __volatile__ ( "icbi @%0\n\t" : : "r" (addr))
+#else
+#define __icbi(addr)   mb()
+#endif
+
+#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp @%0\n\t" : : "r" (addr))
+#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi @%0\n\t" : : "r" (addr))
+#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb @%0\n\t" : : "r" (addr))
+
+static inline reg_size_t register_align(void *val)
+{
+       return (unsigned long)(signed long)val;
+}
+
+#endif /* __ASM_SH_CACHE_INSNS_32_H */
diff --git a/arch/sh/include/asm/cache_insns_64.h b/arch/sh/include/asm/cache_insns_64.h
new file mode 100644 (file)
index 0000000..70b6357
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_CACHE_INSNS_64_H
+#define __ASM_SH_CACHE_INSNS_64_H
+
+#define __icbi(addr)   __asm__ __volatile__ ( "icbi %0, 0\n\t" : : "r" (addr))
+#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp %0, 0\n\t" : : "r" (addr))
+#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi %0, 0\n\t" : : "r" (addr))
+#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb %0, 0\n\t" : : "r" (addr))
+
+static inline reg_size_t register_align(void *val)
+{
+       return (unsigned long long)(signed long long)(signed long)val;
+}
+
+#endif /* __ASM_SH_CACHE_INSNS_64_H */
index 43049ec0554b474ed5367ee10602f895a8bb03c0..bd11f630414ad173640b937c0576a8a12399a42a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_CMPXCHG_IRQ_H
 #define __ASM_SH_CMPXCHG_IRQ_H
 
+#include <linux/irqflags.h>
+
 static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
 {
        unsigned long flags, retval;
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..f6bd140
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef __ASM_SH_CMPXCHG_H
+#define __ASM_SH_CMPXCHG_H
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#if defined(CONFIG_GUSA_RB)
+#include <asm/cmpxchg-grb.h>
+#elif defined(CONFIG_CPU_SH4A)
+#include <asm/cmpxchg-llsc.h>
+#else
+#include <asm/cmpxchg-irq.h>
+#endif
+
+extern void __xchg_called_with_bad_pointer(void);
+
+#define __xchg(ptr, x, size)                           \
+({                                                     \
+       unsigned long __xchg__res;                      \
+       volatile void *__xchg_ptr = (ptr);              \
+       switch (size) {                                 \
+       case 4:                                         \
+               __xchg__res = xchg_u32(__xchg_ptr, x);  \
+               break;                                  \
+       case 1:                                         \
+               __xchg__res = xchg_u8(__xchg_ptr, x);   \
+               break;                                  \
+       default:                                        \
+               __xchg_called_with_bad_pointer();       \
+               __xchg__res = x;                        \
+               break;                                  \
+       }                                               \
+                                                       \
+       __xchg__res;                                    \
+})
+
+#define xchg(ptr,x)    \
+       ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
+
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+               unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+#endif /* __ASM_SH_CMPXCHG_H */
diff --git a/arch/sh/include/asm/exec.h b/arch/sh/include/asm/exec.h
new file mode 100644 (file)
index 0000000..69486a9
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
+ * Copyright (C) 2002 Paul Mundt
+ */
+#ifndef __ASM_SH_EXEC_H
+#define __ASM_SH_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_SH_EXEC_H */
index 6cb9f193a95ea5cc7c7b3471a92758206a394527..63d33129ea2348c9228d42987b7e8dab77887745 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_FUTEX_IRQ_H
 #define __ASM_SH_FUTEX_IRQ_H
 
-#include <asm/system.h>
 
 static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
                                           int *oldval)
index 28c5aa58bb45ec73edd45a3d878704f25eb6564b..35fc8b077cb1c25048e7c697ea34b979f62e93f4 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/errno.h>
 #include <asm/cache.h>
-#include <asm/system.h>
 #include <asm/addrspace.h>
 #include <asm/machvec.h>
 #include <asm/pgtable.h>
index 45d08b6a5ef71de204578bb0569f4fba3c836cbd..2a62017eb2750705d1b07f7defb21532c8ccbf27 100644 (file)
  */
 #define NO_IRQ_IGNORE          ((unsigned int)-1)
 
-/*
- * Convert back and forth between INTEVT and IRQ values.
- */
-#ifdef CONFIG_CPU_HAS_INTEVT
-#define evt2irq(evt)           (((evt) >> 5) - 16)
-#define irq2evt(irq)           (((irq) + 16) << 5)
-#else
-#define evt2irq(evt)           (evt)
-#define irq2evt(irq)           (irq)
-#endif
-
 /*
  * Simple Mask Register Support
  */
index 6a9ceaaf1aea7f0545736634e08d979c3b020e88..abda58467ece9e86ff1249029bcc7143281b2f04 100644 (file)
@@ -12,11 +12,6 @@ typedef unsigned short       __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
 #define __kernel_gid_t __kernel_gid_t
 
-typedef unsigned int   __kernel_uid32_t;
-#define __kernel_uid32_t __kernel_uid32_t
-typedef unsigned int   __kernel_gid32_t;
-#define __kernel_gid32_t __kernel_gid32_t
-
 typedef unsigned short __kernel_old_uid_t;
 #define __kernel_old_uid_t __kernel_old_uid_t
 typedef unsigned short __kernel_old_gid_t;
index 8cd11485c06bc1ac693fcc96f1018a9e209321fd..fcda07b4a616be8196f105ce5d2faee8682c9af1 100644 (file)
@@ -17,10 +17,6 @@ typedef int          __kernel_ssize_t;
 #define __kernel_ssize_t __kernel_ssize_t
 typedef int            __kernel_ptrdiff_t;
 #define __kernel_ptrdiff_t __kernel_ptrdiff_t
-typedef unsigned int   __kernel_uid32_t;
-#define __kernel_uid32_t __kernel_uid32_t
-typedef unsigned int   __kernel_gid32_t;
-#define __kernel_gid32_t __kernel_gid32_t
 
 typedef unsigned short __kernel_old_uid_t;
 #define __kernel_old_uid_t __kernel_old_uid_t
index 9c7bdfcaebbd9642a490de3ca011e53c0d9a85ec..a229c393826ac116e64e48597ac011510ffc4102 100644 (file)
@@ -101,6 +101,10 @@ extern struct sh_cpuinfo cpu_data[];
 #define cpu_sleep()    __asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()    barrier()
 
+void default_idle(void);
+void cpu_idle_wait(void);
+void stop_this_cpu(void *);
+
 /* Forward decl */
 struct seq_operations;
 struct task_struct;
@@ -161,6 +165,17 @@ int vsyscall_init(void);
 #define vsyscall_init() do { } while (0)
 #endif
 
+/*
+ * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
+ */
+#ifdef CONFIG_CPU_SH2A
+extern unsigned int instruction_size(unsigned int insn);
+#elif defined(CONFIG_SUPERH32)
+#define instruction_size(insn) (2)
+#else
+#define instruction_size(insn) (4)
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_SUPERH32
index 2d3679b2447f262c4c83eebe5e6ff89890c2e0a2..c7b7e1ed194af05fd626d1985c01be090a58339c 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/thread_info.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 #define user_mode(regs)                        (((regs)->sr & 0x40000000)==0)
 #define kernel_stack_pointer(_regs)    ((unsigned long)(_regs)->regs[15])
index 01fa17a3d75980319e94828081ce29d37f315b3b..465a22df8fd029baa750e02c47b8ca438e22bd70 100644 (file)
@@ -20,6 +20,7 @@
 
 void sh_mv_setup(void);
 void check_for_initrd(void);
+void per_cpu_trap_init(void);
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/sh/include/asm/switch_to.h b/arch/sh/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..62b1941
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_SWITCH_TO_H
+#define __ASM_SH_SWITCH_TO_H
+
+#ifdef CONFIG_SUPERH32
+# include "switch_to_32.h"
+#else
+# include "switch_to_64.h"
+#endif
+
+#endif /* __ASM_SH_SWITCH_TO_H */
diff --git a/arch/sh/include/asm/switch_to_32.h b/arch/sh/include/asm/switch_to_32.h
new file mode 100644 (file)
index 0000000..0c06551
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __ASM_SH_SWITCH_TO_32_H
+#define __ASM_SH_SWITCH_TO_32_H
+
+#ifdef CONFIG_SH_DSP
+
+#define is_dsp_enabled(tsk)                                            \
+       (!!(tsk->thread.dsp_status.status & SR_DSP))
+
+#define __restore_dsp(tsk)                                             \
+do {                                                                   \
+       register u32 *__ts2 __asm__ ("r2") =                            \
+                       (u32 *)&tsk->thread.dsp_status;                 \
+       __asm__ __volatile__ (                                          \
+               ".balign 4\n\t"                                         \
+               "movs.l @r2+, a0\n\t"                                   \
+               "movs.l @r2+, a1\n\t"                                   \
+               "movs.l @r2+, a0g\n\t"                                  \
+               "movs.l @r2+, a1g\n\t"                                  \
+               "movs.l @r2+, m0\n\t"                                   \
+               "movs.l @r2+, m1\n\t"                                   \
+               "movs.l @r2+, x0\n\t"                                   \
+               "movs.l @r2+, x1\n\t"                                   \
+               "movs.l @r2+, y0\n\t"                                   \
+               "movs.l @r2+, y1\n\t"                                   \
+               "lds.l  @r2+, dsr\n\t"                                  \
+               "ldc.l  @r2+, rs\n\t"                                   \
+               "ldc.l  @r2+, re\n\t"                                   \
+               "ldc.l  @r2+, mod\n\t"                                  \
+               : : "r" (__ts2));                                       \
+} while (0)
+
+#define __save_dsp(tsk)                                                        \
+do {                                                                   \
+       register u32 *__ts2 __asm__ ("r2") =                            \
+                       (u32 *)&tsk->thread.dsp_status + 14;            \
+                                                                       \
+       __asm__ __volatile__ (                                          \
+               ".balign 4\n\t"                                         \
+               "stc.l  mod, @-r2\n\t"                                  \
+               "stc.l  re, @-r2\n\t"                                   \
+               "stc.l  rs, @-r2\n\t"                                   \
+               "sts.l  dsr, @-r2\n\t"                                  \
+               "movs.l y1, @-r2\n\t"                                   \
+               "movs.l y0, @-r2\n\t"                                   \
+               "movs.l x1, @-r2\n\t"                                   \
+               "movs.l x0, @-r2\n\t"                                   \
+               "movs.l m1, @-r2\n\t"                                   \
+               "movs.l m0, @-r2\n\t"                                   \
+               "movs.l a1g, @-r2\n\t"                                  \
+               "movs.l a0g, @-r2\n\t"                                  \
+               "movs.l a1, @-r2\n\t"                                   \
+               "movs.l a0, @-r2\n\t"                                   \
+               : : "r" (__ts2));                                       \
+} while (0)
+
+#else
+
+#define is_dsp_enabled(tsk)    (0)
+#define __save_dsp(tsk)                do { } while (0)
+#define __restore_dsp(tsk)     do { } while (0)
+#endif
+
+struct task_struct *__switch_to(struct task_struct *prev,
+                               struct task_struct *next);
+
+/*
+ *     switch_to() should switch tasks to task nr n, first
+ */
+#define switch_to(prev, next, last)                            \
+do {                                                           \
+       register u32 *__ts1 __asm__ ("r1");                     \
+       register u32 *__ts2 __asm__ ("r2");                     \
+       register u32 *__ts4 __asm__ ("r4");                     \
+       register u32 *__ts5 __asm__ ("r5");                     \
+       register u32 *__ts6 __asm__ ("r6");                     \
+       register u32 __ts7 __asm__ ("r7");                      \
+       struct task_struct *__last;                             \
+                                                               \
+       if (is_dsp_enabled(prev))                               \
+               __save_dsp(prev);                               \
+                                                               \
+       __ts1 = (u32 *)&prev->thread.sp;                        \
+       __ts2 = (u32 *)&prev->thread.pc;                        \
+       __ts4 = (u32 *)prev;                                    \
+       __ts5 = (u32 *)next;                                    \
+       __ts6 = (u32 *)&next->thread.sp;                        \
+       __ts7 = next->thread.pc;                                \
+                                                               \
+       __asm__ __volatile__ (                                  \
+               ".balign 4\n\t"                                 \
+               "stc.l  gbr, @-r15\n\t"                         \
+               "sts.l  pr, @-r15\n\t"                          \
+               "mov.l  r8, @-r15\n\t"                          \
+               "mov.l  r9, @-r15\n\t"                          \
+               "mov.l  r10, @-r15\n\t"                         \
+               "mov.l  r11, @-r15\n\t"                         \
+               "mov.l  r12, @-r15\n\t"                         \
+               "mov.l  r13, @-r15\n\t"                         \
+               "mov.l  r14, @-r15\n\t"                         \
+               "mov.l  r15, @r1\t! save SP\n\t"                \
+               "mov.l  @r6, r15\t! change to new stack\n\t"    \
+               "mova   1f, %0\n\t"                             \
+               "mov.l  %0, @r2\t! save PC\n\t"                 \
+               "mov.l  2f, %0\n\t"                             \
+               "jmp    @%0\t! call __switch_to\n\t"            \
+               " lds   r7, pr\t!  with return to new PC\n\t"   \
+               ".balign        4\n"                            \
+               "2:\n\t"                                        \
+               ".long  __switch_to\n"                          \
+               "1:\n\t"                                        \
+               "mov.l  @r15+, r14\n\t"                         \
+               "mov.l  @r15+, r13\n\t"                         \
+               "mov.l  @r15+, r12\n\t"                         \
+               "mov.l  @r15+, r11\n\t"                         \
+               "mov.l  @r15+, r10\n\t"                         \
+               "mov.l  @r15+, r9\n\t"                          \
+               "mov.l  @r15+, r8\n\t"                          \
+               "lds.l  @r15+, pr\n\t"                          \
+               "ldc.l  @r15+, gbr\n\t"                         \
+               : "=z" (__last)                                 \
+               : "r" (__ts1), "r" (__ts2), "r" (__ts4),        \
+                 "r" (__ts5), "r" (__ts6), "r" (__ts7)         \
+               : "r3", "t");                                   \
+                                                               \
+       last = __last;                                          \
+} while (0)
+
+#define finish_arch_switch(prev)                               \
+do {                                                           \
+       if (is_dsp_enabled(prev))                               \
+               __restore_dsp(prev);                            \
+} while (0)
+
+#endif /* __ASM_SH_SWITCH_TO_32_H */
diff --git a/arch/sh/include/asm/switch_to_64.h b/arch/sh/include/asm/switch_to_64.h
new file mode 100644 (file)
index 0000000..ba3129d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_SWITCH_TO_64_H
+#define __ASM_SH_SWITCH_TO_64_H
+
+struct thread_struct;
+struct task_struct;
+
+/*
+ *     switch_to() should switch tasks to task nr n, first
+ */
+struct task_struct *sh64_switch_to(struct task_struct *prev,
+                                  struct thread_struct *prev_thread,
+                                  struct task_struct *next,
+                                  struct thread_struct *next_thread);
+
+#define switch_to(prev,next,last)                              \
+do {                                                           \
+       if (last_task_used_math != next) {                      \
+               struct pt_regs *regs = next->thread.uregs;      \
+               if (regs) regs->sr |= SR_FD;                    \
+       }                                                       \
+       last = sh64_switch_to(prev, &prev->thread, next,        \
+                             &next->thread);                   \
+} while (0)
+
+
+#endif /* __ASM_SH_SWITCH_TO_64_H */
diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h
deleted file mode 100644 (file)
index 10c8b18..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-#ifndef __ASM_SH_SYSTEM_H
-#define __ASM_SH_SYSTEM_H
-
-/*
- * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
- * Copyright (C) 2002 Paul Mundt
- */
-
-#include <linux/irqflags.h>
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <asm/types.h>
-#include <asm/uncached.h>
-
-#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
-
-/*
- * A brief note on ctrl_barrier(), the control register write barrier.
- *
- * Legacy SH cores typically require a sequence of 8 nops after
- * modification of a control register in order for the changes to take
- * effect. On newer cores (like the sh4a and sh5) this is accomplished
- * with icbi.
- *
- * Also note that on sh4a in the icbi case we can forego a synco for the
- * write barrier, as it's not necessary for control registers.
- *
- * Historically we have only done this type of barrier for the MMUCR, but
- * it's also necessary for the CCR, so we make it generic here instead.
- */
-#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
-#define mb()           __asm__ __volatile__ ("synco": : :"memory")
-#define rmb()          mb()
-#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
-#define ctrl_barrier() __icbi(PAGE_OFFSET)
-#define read_barrier_depends() do { } while(0)
-#else
-#define mb()           __asm__ __volatile__ ("": : :"memory")
-#define rmb()          mb()
-#define wmb()          __asm__ __volatile__ ("": : :"memory")
-#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
-#define read_barrier_depends() do { } while(0)
-#endif
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-
-#ifdef CONFIG_GUSA_RB
-#include <asm/cmpxchg-grb.h>
-#elif defined(CONFIG_CPU_SH4A)
-#include <asm/cmpxchg-llsc.h>
-#else
-#include <asm/cmpxchg-irq.h>
-#endif
-
-extern void __xchg_called_with_bad_pointer(void);
-
-#define __xchg(ptr, x, size)                           \
-({                                                     \
-       unsigned long __xchg__res;                      \
-       volatile void *__xchg_ptr = (ptr);              \
-       switch (size) {                                 \
-       case 4:                                         \
-               __xchg__res = xchg_u32(__xchg_ptr, x);  \
-               break;                                  \
-       case 1:                                         \
-               __xchg__res = xchg_u8(__xchg_ptr, x);   \
-               break;                                  \
-       default:                                        \
-               __xchg_called_with_bad_pointer();       \
-               __xchg__res = x;                        \
-               break;                                  \
-       }                                               \
-                                                       \
-       __xchg__res;                                    \
-})
-
-#define xchg(ptr,x)    \
-       ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
-
-/* This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg(). */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
-               unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)                                                \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-struct pt_regs;
-
-extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
-void free_initmem(void);
-void free_initrd_mem(unsigned long start, unsigned long end);
-
-extern void *set_exception_table_vec(unsigned int vec, void *handler);
-
-static inline void *set_exception_table_evt(unsigned int evt, void *handler)
-{
-       return set_exception_table_vec(evt >> 5, handler);
-}
-
-/*
- * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
- */
-#ifdef CONFIG_CPU_SH2A
-extern unsigned int instruction_size(unsigned int insn);
-#elif defined(CONFIG_SUPERH32)
-#define instruction_size(insn) (2)
-#else
-#define instruction_size(insn) (4)
-#endif
-
-void per_cpu_trap_init(void);
-void default_idle(void);
-void cpu_idle_wait(void);
-void stop_this_cpu(void *);
-
-#ifdef CONFIG_SUPERH32
-#define BUILD_TRAP_HANDLER(name)                                       \
-asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5,        \
-                                   unsigned long r6, unsigned long r7, \
-                                   struct pt_regs __regs)
-
-#define TRAP_HANDLER_DECL                              \
-       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);  \
-       unsigned int vec = regs->tra;                   \
-       (void)vec;
-#else
-#define BUILD_TRAP_HANDLER(name)       \
-asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs)
-#define TRAP_HANDLER_DECL
-#endif
-
-BUILD_TRAP_HANDLER(address_error);
-BUILD_TRAP_HANDLER(debug);
-BUILD_TRAP_HANDLER(bug);
-BUILD_TRAP_HANDLER(breakpoint);
-BUILD_TRAP_HANDLER(singlestep);
-BUILD_TRAP_HANDLER(fpu_error);
-BUILD_TRAP_HANDLER(fpu_state_restore);
-BUILD_TRAP_HANDLER(nmi);
-
-#define arch_align_stack(x) (x)
-
-struct mem_access {
-       unsigned long (*from)(void *dst, const void __user *src, unsigned long cnt);
-       unsigned long (*to)(void __user *dst, const void *src, unsigned long cnt);
-};
-
-#ifdef CONFIG_SUPERH32
-# include "system_32.h"
-#else
-# include "system_64.h"
-#endif
-
-#endif
diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h
deleted file mode 100644 (file)
index a4ad1cd..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-#ifndef __ASM_SH_SYSTEM_32_H
-#define __ASM_SH_SYSTEM_32_H
-
-#include <linux/types.h>
-#include <asm/mmu.h>
-
-#ifdef CONFIG_SH_DSP
-
-#define is_dsp_enabled(tsk)                                            \
-       (!!(tsk->thread.dsp_status.status & SR_DSP))
-
-#define __restore_dsp(tsk)                                             \
-do {                                                                   \
-       register u32 *__ts2 __asm__ ("r2") =                            \
-                       (u32 *)&tsk->thread.dsp_status;                 \
-       __asm__ __volatile__ (                                          \
-               ".balign 4\n\t"                                         \
-               "movs.l @r2+, a0\n\t"                                   \
-               "movs.l @r2+, a1\n\t"                                   \
-               "movs.l @r2+, a0g\n\t"                                  \
-               "movs.l @r2+, a1g\n\t"                                  \
-               "movs.l @r2+, m0\n\t"                                   \
-               "movs.l @r2+, m1\n\t"                                   \
-               "movs.l @r2+, x0\n\t"                                   \
-               "movs.l @r2+, x1\n\t"                                   \
-               "movs.l @r2+, y0\n\t"                                   \
-               "movs.l @r2+, y1\n\t"                                   \
-               "lds.l  @r2+, dsr\n\t"                                  \
-               "ldc.l  @r2+, rs\n\t"                                   \
-               "ldc.l  @r2+, re\n\t"                                   \
-               "ldc.l  @r2+, mod\n\t"                                  \
-               : : "r" (__ts2));                                       \
-} while (0)
-
-
-#define __save_dsp(tsk)                                                        \
-do {                                                                   \
-       register u32 *__ts2 __asm__ ("r2") =                            \
-                       (u32 *)&tsk->thread.dsp_status + 14;            \
-                                                                       \
-       __asm__ __volatile__ (                                          \
-               ".balign 4\n\t"                                         \
-               "stc.l  mod, @-r2\n\t"                                  \
-               "stc.l  re, @-r2\n\t"                                   \
-               "stc.l  rs, @-r2\n\t"                                   \
-               "sts.l  dsr, @-r2\n\t"                                  \
-               "movs.l y1, @-r2\n\t"                                   \
-               "movs.l y0, @-r2\n\t"                                   \
-               "movs.l x1, @-r2\n\t"                                   \
-               "movs.l x0, @-r2\n\t"                                   \
-               "movs.l m1, @-r2\n\t"                                   \
-               "movs.l m0, @-r2\n\t"                                   \
-               "movs.l a1g, @-r2\n\t"                                  \
-               "movs.l a0g, @-r2\n\t"                                  \
-               "movs.l a1, @-r2\n\t"                                   \
-               "movs.l a0, @-r2\n\t"                                   \
-               : : "r" (__ts2));                                       \
-} while (0)
-
-#else
-
-#define is_dsp_enabled(tsk)    (0)
-#define __save_dsp(tsk)                do { } while (0)
-#define __restore_dsp(tsk)     do { } while (0)
-#endif
-
-#if defined(CONFIG_CPU_SH4A)
-#define __icbi(addr)   __asm__ __volatile__ ( "icbi @%0\n\t" : : "r" (addr))
-#else
-#define __icbi(addr)   mb()
-#endif
-
-#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp @%0\n\t" : : "r" (addr))
-#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi @%0\n\t" : : "r" (addr))
-#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb @%0\n\t" : : "r" (addr))
-
-struct task_struct *__switch_to(struct task_struct *prev,
-                               struct task_struct *next);
-
-/*
- *     switch_to() should switch tasks to task nr n, first
- */
-#define switch_to(prev, next, last)                            \
-do {                                                           \
-       register u32 *__ts1 __asm__ ("r1");                     \
-       register u32 *__ts2 __asm__ ("r2");                     \
-       register u32 *__ts4 __asm__ ("r4");                     \
-       register u32 *__ts5 __asm__ ("r5");                     \
-       register u32 *__ts6 __asm__ ("r6");                     \
-       register u32 __ts7 __asm__ ("r7");                      \
-       struct task_struct *__last;                             \
-                                                               \
-       if (is_dsp_enabled(prev))                               \
-               __save_dsp(prev);                               \
-                                                               \
-       __ts1 = (u32 *)&prev->thread.sp;                        \
-       __ts2 = (u32 *)&prev->thread.pc;                        \
-       __ts4 = (u32 *)prev;                                    \
-       __ts5 = (u32 *)next;                                    \
-       __ts6 = (u32 *)&next->thread.sp;                        \
-       __ts7 = next->thread.pc;                                \
-                                                               \
-       __asm__ __volatile__ (                                  \
-               ".balign 4\n\t"                                 \
-               "stc.l  gbr, @-r15\n\t"                         \
-               "sts.l  pr, @-r15\n\t"                          \
-               "mov.l  r8, @-r15\n\t"                          \
-               "mov.l  r9, @-r15\n\t"                          \
-               "mov.l  r10, @-r15\n\t"                         \
-               "mov.l  r11, @-r15\n\t"                         \
-               "mov.l  r12, @-r15\n\t"                         \
-               "mov.l  r13, @-r15\n\t"                         \
-               "mov.l  r14, @-r15\n\t"                         \
-               "mov.l  r15, @r1\t! save SP\n\t"                \
-               "mov.l  @r6, r15\t! change to new stack\n\t"    \
-               "mova   1f, %0\n\t"                             \
-               "mov.l  %0, @r2\t! save PC\n\t"                 \
-               "mov.l  2f, %0\n\t"                             \
-               "jmp    @%0\t! call __switch_to\n\t"            \
-               " lds   r7, pr\t!  with return to new PC\n\t"   \
-               ".balign        4\n"                            \
-               "2:\n\t"                                        \
-               ".long  __switch_to\n"                          \
-               "1:\n\t"                                        \
-               "mov.l  @r15+, r14\n\t"                         \
-               "mov.l  @r15+, r13\n\t"                         \
-               "mov.l  @r15+, r12\n\t"                         \
-               "mov.l  @r15+, r11\n\t"                         \
-               "mov.l  @r15+, r10\n\t"                         \
-               "mov.l  @r15+, r9\n\t"                          \
-               "mov.l  @r15+, r8\n\t"                          \
-               "lds.l  @r15+, pr\n\t"                          \
-               "ldc.l  @r15+, gbr\n\t"                         \
-               : "=z" (__last)                                 \
-               : "r" (__ts1), "r" (__ts2), "r" (__ts4),        \
-                 "r" (__ts5), "r" (__ts6), "r" (__ts7)         \
-               : "r3", "t");                                   \
-                                                               \
-       last = __last;                                          \
-} while (0)
-
-#define finish_arch_switch(prev)                               \
-do {                                                           \
-       if (is_dsp_enabled(prev))                               \
-               __restore_dsp(prev);                            \
-} while (0)
-
-#ifdef CONFIG_CPU_HAS_SR_RB
-#define lookup_exception_vector()      \
-({                                     \
-       unsigned long _vec;             \
-                                       \
-       __asm__ __volatile__ (          \
-               "stc r2_bank, %0\n\t"   \
-               : "=r" (_vec)           \
-       );                              \
-                                       \
-       _vec;                           \
-})
-#else
-#define lookup_exception_vector()      \
-({                                     \
-       unsigned long _vec;             \
-       __asm__ __volatile__ (          \
-               "mov r4, %0\n\t"        \
-               : "=r" (_vec)           \
-       );                              \
-                                       \
-       _vec;                           \
-})
-#endif
-
-static inline reg_size_t register_align(void *val)
-{
-       return (unsigned long)(signed long)val;
-}
-
-int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma, int, unsigned long address);
-
-static inline void trigger_address_error(void)
-{
-       __asm__ __volatile__ (
-               "ldc %0, sr\n\t"
-               "mov.l @%1, %0"
-               :
-               : "r" (0x10000000), "r" (0x80000001)
-       );
-}
-
-asmlinkage void do_address_error(struct pt_regs *regs,
-                                unsigned long writeaccess,
-                                unsigned long address);
-asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
-                               unsigned long r6, unsigned long r7,
-                               struct pt_regs __regs);
-asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
-                               unsigned long r6, unsigned long r7,
-                               struct pt_regs __regs);
-asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
-                               unsigned long r6, unsigned long r7,
-                               struct pt_regs __regs);
-asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
-                                  unsigned long r6, unsigned long r7,
-                                  struct pt_regs __regs);
-
-static inline void set_bl_bit(void)
-{
-       unsigned long __dummy0, __dummy1;
-
-       __asm__ __volatile__ (
-               "stc    sr, %0\n\t"
-               "or     %2, %0\n\t"
-               "and    %3, %0\n\t"
-               "ldc    %0, sr\n\t"
-               : "=&r" (__dummy0), "=r" (__dummy1)
-               : "r" (0x10000000), "r" (0xffffff0f)
-               : "memory"
-       );
-}
-
-static inline void clear_bl_bit(void)
-{
-       unsigned long __dummy0, __dummy1;
-
-       __asm__ __volatile__ (
-               "stc    sr, %0\n\t"
-               "and    %2, %0\n\t"
-               "ldc    %0, sr\n\t"
-               : "=&r" (__dummy0), "=r" (__dummy1)
-               : "1" (~0x10000000)
-               : "memory"
-       );
-}
-
-#endif /* __ASM_SH_SYSTEM_32_H */
diff --git a/arch/sh/include/asm/system_64.h b/arch/sh/include/asm/system_64.h
deleted file mode 100644 (file)
index 8593bc8..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef __ASM_SH_SYSTEM_64_H
-#define __ASM_SH_SYSTEM_64_H
-
-/*
- * include/asm-sh/system_64.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003  Paul Mundt
- * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <cpu/registers.h>
-#include <asm/processor.h>
-
-/*
- *     switch_to() should switch tasks to task nr n, first
- */
-struct thread_struct;
-struct task_struct *sh64_switch_to(struct task_struct *prev,
-                                  struct thread_struct *prev_thread,
-                                  struct task_struct *next,
-                                  struct thread_struct *next_thread);
-
-#define switch_to(prev,next,last)                              \
-do {                                                           \
-       if (last_task_used_math != next) {                      \
-               struct pt_regs *regs = next->thread.uregs;      \
-               if (regs) regs->sr |= SR_FD;                    \
-       }                                                       \
-       last = sh64_switch_to(prev, &prev->thread, next,        \
-                             &next->thread);                   \
-} while (0)
-
-#define __icbi(addr)   __asm__ __volatile__ ( "icbi %0, 0\n\t" : : "r" (addr))
-#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp %0, 0\n\t" : : "r" (addr))
-#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi %0, 0\n\t" : : "r" (addr))
-#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb %0, 0\n\t" : : "r" (addr))
-
-static inline reg_size_t register_align(void *val)
-{
-       return (unsigned long long)(signed long long)(signed long)val;
-}
-
-extern void phys_stext(void);
-
-static inline void trigger_address_error(void)
-{
-       phys_stext();
-}
-
-#define SR_BL_LL       0x0000000010000000LL
-
-static inline void set_bl_bit(void)
-{
-       unsigned long long __dummy0, __dummy1 = SR_BL_LL;
-
-       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
-                            "or        %0, %1, %0\n\t"
-                            "putcon    %0, " __SR "\n\t"
-                            : "=&r" (__dummy0)
-                            : "r" (__dummy1));
-
-}
-
-static inline void clear_bl_bit(void)
-{
-       unsigned long long __dummy0, __dummy1 = ~SR_BL_LL;
-
-       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
-                            "and       %0, %1, %0\n\t"
-                            "putcon    %0, " __SR "\n\t"
-                            : "=&r" (__dummy0)
-                            : "r" (__dummy1));
-}
-
-#endif /* __ASM_SH_SYSTEM_64_H */
diff --git a/arch/sh/include/asm/traps.h b/arch/sh/include/asm/traps.h
new file mode 100644 (file)
index 0000000..afd9df8
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_TRAPS_H
+#define __ASM_SH_TRAPS_H
+
+#include <linux/compiler.h>
+
+#ifdef CONFIG_SUPERH32
+# include "traps_32.h"
+#else
+# include "traps_64.h"
+#endif
+
+BUILD_TRAP_HANDLER(address_error);
+BUILD_TRAP_HANDLER(debug);
+BUILD_TRAP_HANDLER(bug);
+BUILD_TRAP_HANDLER(breakpoint);
+BUILD_TRAP_HANDLER(singlestep);
+BUILD_TRAP_HANDLER(fpu_error);
+BUILD_TRAP_HANDLER(fpu_state_restore);
+BUILD_TRAP_HANDLER(nmi);
+
+#endif /* __ASM_SH_TRAPS_H */
diff --git a/arch/sh/include/asm/traps_32.h b/arch/sh/include/asm/traps_32.h
new file mode 100644 (file)
index 0000000..cfd55ff
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __ASM_SH_TRAPS_32_H
+#define __ASM_SH_TRAPS_32_H
+
+#include <linux/types.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_CPU_HAS_SR_RB
+#define lookup_exception_vector()      \
+({                                     \
+       unsigned long _vec;             \
+                                       \
+       __asm__ __volatile__ (          \
+               "stc r2_bank, %0\n\t"   \
+               : "=r" (_vec)           \
+       );                              \
+                                       \
+       _vec;                           \
+})
+#else
+#define lookup_exception_vector()      \
+({                                     \
+       unsigned long _vec;             \
+       __asm__ __volatile__ (          \
+               "mov r4, %0\n\t"        \
+               : "=r" (_vec)           \
+       );                              \
+                                       \
+       _vec;                           \
+})
+#endif
+
+static inline void trigger_address_error(void)
+{
+       __asm__ __volatile__ (
+               "ldc %0, sr\n\t"
+               "mov.l @%1, %0"
+               :
+               : "r" (0x10000000), "r" (0x80000001)
+       );
+}
+
+asmlinkage void do_address_error(struct pt_regs *regs,
+                                unsigned long writeaccess,
+                                unsigned long address);
+asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
+                                  unsigned long r6, unsigned long r7,
+                                  struct pt_regs __regs);
+
+#define BUILD_TRAP_HANDLER(name)                                       \
+asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5,        \
+                                   unsigned long r6, unsigned long r7, \
+                                   struct pt_regs __regs)
+
+#define TRAP_HANDLER_DECL                              \
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);  \
+       unsigned int vec = regs->tra;                   \
+       (void)vec;
+
+#endif /* __ASM_SH_TRAPS_32_H */
diff --git a/arch/sh/include/asm/traps_64.h b/arch/sh/include/asm/traps_64.h
new file mode 100644 (file)
index 0000000..c52d7f9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_TRAPS_64_H
+#define __ASM_SH_TRAPS_64_H
+
+extern void phys_stext(void);
+
+static inline void trigger_address_error(void)
+{
+       phys_stext();
+}
+
+#define BUILD_TRAP_HANDLER(name)       \
+asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs)
+#define TRAP_HANDLER_DECL
+
+#endif /* __ASM_SH_TRAPS_64_H */
index 075848f43b6a1ee63890310323f3cc4749764a6d..050f221fa898219b40e2faca0bbb9cebae93dd7e 100644 (file)
@@ -254,5 +254,19 @@ int fixup_exception(struct pt_regs *regs);
 unsigned long search_exception_table(unsigned long addr);
 const struct exception_table_entry *search_exception_tables(unsigned long addr);
 
+extern void *set_exception_table_vec(unsigned int vec, void *handler);
+
+static inline void *set_exception_table_evt(unsigned int evt, void *handler)
+{
+       return set_exception_table_vec(evt >> 5, handler);
+}
+
+struct mem_access {
+       unsigned long (*from)(void *dst, const void __user *src, unsigned long cnt);
+       unsigned long (*to)(void __user *dst, const void *src, unsigned long cnt);
+};
+
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
+                           struct mem_access *ma, int, unsigned long address);
 
 #endif /* __ASM_SH_UACCESS_H */
index fac742e514eec3257ea493c14eb0100796c01cec..61a07dafcd46cbaaae3c1c36ad48218e47944f82 100644 (file)
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
 #include <asm/elf.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/sh_bios.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_SH_FPU
 #define cpu_has_fpu    1
index 39b6a24c159d96081854dbd59d02f94d4db5e8a5..e7f1745bd12120055977da02c095840d50487802 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/cache.h>
 #include <linux/irq.h>
 #include <linux/bitmap.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 /* Bitmap of IRQ masked */
index 9704b7926d8bd30706c19dbb54952d554b708a93..72aa61c81e485389107755bdbf5fd8707d6f4cff 100644 (file)
@@ -10,7 +10,6 @@
  * for more details.
  */
 #include <linux/kernel.h>
-#include <asm/system.h>
 
 /*
  * Instructions on SH are generally fixed at 16-bits, however, SH-2A
index 447482d7f65e6bdf573c33dabe67317afbe19cdd..e74cd6c0f10de9c5b94078de2ada8ddd5afa47d9 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/io.h>
 #include <cpu/fpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
index efae6ab3d54ca0d8fe1b84da78280ec67cc4cd21..f9173766ec4be2393e4207efe7092741f35fc271 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/mmu_context.h>
 #include <asm/ptrace.h>
+#include <asm/traps.h>
 
 /*
  * Stores the breakpoints currently in use on each breakpoint address
index 7e4892826563e73b47f7e4364a41ad06f959beea..64852ecc6881ecab8646ad6ff59a1e2643941e69 100644 (file)
@@ -18,9 +18,9 @@
 #include <linux/smp.h>
 #include <linux/cpuidle.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/smp.h>
+#include <asm/bl_bit.h>
 
 void (*pm_idle)(void);
 
index 0f62f467275403554b018f26463cf7887592bf16..c0a9761f2f8a05fa6e6d46b6306e0f4cea0bf6c7 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
index 7ec6651781255e375f971c3645d73eb46f870063..f72e3a951588297fe59ed0f310574f75cd2be17b 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/prefetch.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
 
index cbd4e4bb9fc526796fbbd8b79a60847e0493bfb2..4264583eabac52a292a4a3c79281b858020cd62d 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/fpu.h>
+#include <asm/switch_to.h>
 
 struct task_struct *last_task_used_math = NULL;
 
index a3e651563763aaabf76818e68729a53bc98aeaf7..9698671444e6706c1cb7e7d5599416a091cf9e64 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
index 3d0080b5c976bb9b19fbbc8ac5116239c7d841e3..bc81e07dc098369485fc22800960c33976b56bc9 100644 (file)
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 #include <asm/fpu.h>
+#include <asm/traps.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
index ca6a5ca64015bf223e64e1303e07bdfa17fd03e8..04afe5b206633ff32c887adf8d259e5a90a97c98 100644 (file)
@@ -8,8 +8,8 @@
 #endif
 #include <asm/addrspace.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
+#include <asm/traps.h>
 
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
index a7a55ed43a596ee3b372efaa849d19b8c10b3bfc..0bc58866add1d932c69346cd6169db54bb08a6a5 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/freezer.h>
 #include <linux/io.h>
 #include <linux/tracehook.h>
-#include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
index f624174bf239c6164da323353c15986963e63829..a17a14d32340fb1c537955b3b1266d20cfe3576d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/sched.h>
 #include <linux/atomic.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 #include <asm/cacheflush.h>
index 0830c2a9f712bfad77aaff2bb3a823717a567389..a87e58a9e38fe17ffe37219d56d854ddf0be48b4 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
 #include <asm/unwinder.h>
-#include <asm/system.h>
+#include <asm/traps.h>
 
 #ifdef CONFIG_GENERIC_BUG
 static void handle_BUG(struct pt_regs *regs)
index 7bbef95c9d1b4eb8daa1ffd055d57ea5e8bc6af2..a37175deb73fdfa672c604ddab07297c41559981 100644 (file)
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
 #include <linux/perf_event.h>
-#include <asm/system.h>
 #include <asm/alignment.h>
 #include <asm/fpu.h>
 #include <asm/kprobes.h>
+#include <asm/traps.h>
+#include <asm/bl_bit.h>
 
 #ifdef CONFIG_CPU_SH2
 # define TRAP_RESERVED_INST    4
index cd3a4048329915cb40defbc5bbff26b83dd9a829..6c0486094e48cd074a4fd43cb59ea4db9bd8769c 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/sysctl.h>
 #include <linux/module.h>
 #include <linux/perf_event.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 977195210653ede066d541f39e75ebb2745e55c6..b876780c1e1cbd1fa47a5b200847af03e9bdd074 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/signal.h>
 #include <linux/perf_event.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/io.h>
index 7bebd044f2a1fc02f598c3293a358064784c2045..324eef93c90068ae91d202aebe986339aa8bf192 100644 (file)
@@ -17,9 +17,9 @@
 #include <linux/kprobes.h>
 #include <linux/perf_event.h>
 #include <asm/io_trapped.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
+#include <asm/traps.h>
 
 static inline int notify_page_fault(struct pt_regs *regs, int trap)
 {
index 2b356cec24896ddaf3b37ac0f3dbd2583f45244c..44a341029e7bcbbc563fd3e838b2241c0ea62cc1 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 #include <asm/tlb.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
index cef402678f42b77728b749530387ce8f45267d50..75a17f5bfa1478f906d1b4c9dbcffc5b82b7badf 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
+#include <asm/traps.h>
 
 /*
  * Write back the dirty D-caches, but not invalidate them.
index fad52f1f6812a7515b663ad7795184d7319ad416..7160c9fd6fe3ab3e4283d440032396bbf65c453c 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/vmalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
index b71db6af806088b1d3d84dd4a214b139e44a8700..4db21adfe5debaf3130c91431ab9de90819276f7 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
index 7a940dbfc2e9d0ecccf71c342b816a9f7bebf577..6554fb439f0e5c01c8ca8ea7bc6b0d06303b90a4 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
index cfdf7930d2946723262ea5eaf1d1b3f1595eef2e..d42dd7e443d5ae53e2ab5f27bcf4ce8f20dbb6cd 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
index e3430e093d436d300bb1928ea4320ce230b1d632..11c5a18f10ed9655c5fbc7acc6e5202b28b05e93 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
index 1666de84d477e6e72c00689f1011247501e42db1..6c0683d3fcba837e26907ea03e07ecf4e32a3a3d 100644 (file)
@@ -577,6 +577,7 @@ config COMPAT
        depends on SPARC64
        default y
        select COMPAT_BINFMT_ELF
+       select ARCH_WANT_OLD_COMPAT_IPC
 
 config SYSVIPC_COMPAT
        bool
index 9dd0a769fa18a8656b31f0c07838845afc46d33e..905832aa9e9ec0c4d6520567e61d26e96fda0d97 100644 (file)
@@ -13,9 +13,9 @@
 
 #include <linux/types.h>
 
+#include <asm/cmpxchg.h>
 #include <asm-generic/atomic64.h>
 
-#include <asm/system.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
index 9f421df46aecade24100d68d81b86369c9c9583d..ce35a1cf1a20b0b6f2ab7ae424c7ced8cc3da2f2 100644 (file)
@@ -8,7 +8,7 @@
 #define __ARCH_SPARC64_ATOMIC__
 
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 #define ATOMIC64_INIT(i)       { (i) }
@@ -85,7 +85,6 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
        return c;
 }
 
-
 #define atomic64_cmpxchg(v, o, n) \
        ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
index e03e088be95f23eb2b01a1ab2915a22e47beb7dd..3a319775ae376140d9d0bf89e700cd078b1db18f 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _SPARC_AUXIO_H
 #define _SPARC_AUXIO_H
 
-#include <asm/system.h>
 #include <asm/vaddrs.h>
 
 /* This register is an unsigned char in IO space.  It does two things.
diff --git a/arch/sparc/include/asm/barrier.h b/arch/sparc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..b25f02a
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_BARRIER_H
+#define ___ASM_SPARC_BARRIER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/barrier_64.h>
+#else
+#include <asm/barrier_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/barrier_32.h b/arch/sparc/include/asm/barrier_32.h
new file mode 100644 (file)
index 0000000..c1b7665
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __SPARC_BARRIER_H
+#define __SPARC_BARRIER_H
+
+/* XXX Change this if we ever use a PSO mode kernel. */
+#define mb()   __asm__ __volatile__ ("" : : : "memory")
+#define rmb()  mb()
+#define wmb()  mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
+#define smp_mb()       __asm__ __volatile__("":::"memory")
+#define smp_rmb()      __asm__ __volatile__("":::"memory")
+#define smp_wmb()      __asm__ __volatile__("":::"memory")
+#define smp_read_barrier_depends()     do { } while(0)
+
+#endif /* !(__SPARC_BARRIER_H) */
diff --git a/arch/sparc/include/asm/barrier_64.h b/arch/sparc/include/asm/barrier_64.h
new file mode 100644 (file)
index 0000000..95d4598
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __SPARC64_BARRIER_H
+#define __SPARC64_BARRIER_H
+
+/* These are here in an effort to more fully work around Spitfire Errata
+ * #51.  Essentially, if a memory barrier occurs soon after a mispredicted
+ * branch, the chip can stop executing instructions until a trap occurs.
+ * Therefore, if interrupts are disabled, the chip can hang forever.
+ *
+ * It used to be believed that the memory barrier had to be right in the
+ * delay slot, but a case has been traced recently wherein the memory barrier
+ * was one instruction after the branch delay slot and the chip still hung.
+ * The offending sequence was the following in sym_wakeup_done() of the
+ * sym53c8xx_2 driver:
+ *
+ *     call    sym_ccb_from_dsa, 0
+ *      movge  %icc, 0, %l0
+ *     brz,pn  %o0, .LL1303
+ *      mov    %o0, %l2
+ *     membar  #LoadLoad
+ *
+ * The branch has to be mispredicted for the bug to occur.  Therefore, we put
+ * the memory barrier explicitly into a "branch always, predicted taken"
+ * delay slot to avoid the problem case.
+ */
+#define membar_safe(type) \
+do {   __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
+                            " membar   " type "\n" \
+                            "1:\n" \
+                            : : : "memory"); \
+} while (0)
+
+/* The kernel always executes in TSO memory model these days,
+ * and furthermore most sparc64 chips implement more stringent
+ * memory ordering than required by the specifications.
+ */
+#define mb()   membar_safe("#StoreLoad")
+#define rmb()  __asm__ __volatile__("":::"memory")
+#define wmb()  __asm__ __volatile__("":::"memory")
+
+#define read_barrier_depends()         do { } while(0)
+#define set_mb(__var, __value) \
+       do { __var = __value; membar_safe("#StoreLoad"); } while(0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#else
+#define smp_mb()       __asm__ __volatile__("":::"memory")
+#define smp_rmb()      __asm__ __volatile__("":::"memory")
+#define smp_wmb()      __asm__ __volatile__("":::"memory")
+#endif
+
+#define smp_read_barrier_depends()     do { } while(0)
+
+#endif /* !(__SPARC64_BARRIER_H) */
index 8a59e5a8c21727923f83e8090210a48c8e7d6ded..6bd9f43cb5a5471bccb1aee3cb14dcf89d2b76b7 100644 (file)
@@ -19,4 +19,7 @@ extern void do_BUG(const char *file, int line);
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
+
 #endif
index 2e468773f250f788676c835524927946ddafde7e..68431b47a22a24cad38d05dc0d512126f58a8cee 100644 (file)
@@ -83,4 +83,13 @@ extern void sparc_flush_page_to_ram(struct page *page);
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
 
+/* When a context switch happens we must flush all user windows so that
+ * the windows of the current process are flushed onto its stack. This
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
+ */
+extern void flush_user_windows(void);
+extern void kill_user_windows(void);
+extern void flushw_all(void);
+
 #endif /* _SPARC_CACHEFLUSH_H */
index b95384033e89fa264304fc2f4c84277a8bed6918..2efea2ff88b7d4571920b0dca517dfb4edb81470 100644 (file)
@@ -9,6 +9,16 @@
 
 /* Cache flush operations. */
 
+
+#define flushi(addr)   __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
+#define flushw_all()   __asm__ __volatile__("flushw")
+
+extern void __flushw_user(void);
+#define flushw_user() __flushw_user()
+
+#define flush_user_windows flushw_user
+#define flush_register_windows flushw_all
+
 /* These are the same regardless of whether this is an SMP kernel or not. */
 #define flush_cache_mm(__mm) \
        do { if ((__mm) == current->mm) flushw_user(); } while(0)
diff --git a/arch/sparc/include/asm/cmpxchg.h b/arch/sparc/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..9355893
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_CMPXCHG_H
+#define ___ASM_SPARC_CMPXCHG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cmpxchg_64.h>
+#else
+#include <asm/cmpxchg_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h
new file mode 100644 (file)
index 0000000..c786b0a
--- /dev/null
@@ -0,0 +1,112 @@
+/* 32-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_CMPXCHG__
+#define __ARCH_SPARC_CMPXCHG__
+
+#include <asm/btfixup.h>
+
+/* This has special calling conventions */
+#ifndef CONFIG_SMP
+BTFIXUPDEF_CALL(void, ___xchg32, void)
+#endif
+
+static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
+{
+#ifdef CONFIG_SMP
+       __asm__ __volatile__("swap [%2], %0"
+                            : "=&r" (val)
+                            : "0" (val), "r" (m)
+                            : "memory");
+       return val;
+#else
+       register unsigned long *ptr asm("g1");
+       register unsigned long ret asm("g2");
+
+       ptr = (unsigned long *) m;
+       ret = val;
+
+       /* Note: this is magic and the nop there is
+          really needed. */
+       __asm__ __volatile__(
+       "mov    %%o7, %%g4\n\t"
+       "call   ___f____xchg32\n\t"
+       " nop\n\t"
+       : "=&r" (ret)
+       : "0" (ret), "r" (ptr)
+       : "g3", "g4", "g7", "memory", "cc");
+
+       return ret;
+#endif
+}
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+       switch (size) {
+       case 4:
+               return xchg_u32(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/* Emulate cmpxchg() the same way we emulate atomics,
+ * by hashing the object address and indexing into an array
+ * of spinlocks to get a bit of performance...
+ *
+ * See arch/sparc/lib/atomic32.c for implementation.
+ *
+ * Cribbed from <asm-parisc/atomic.h>
+ */
+#define __HAVE_ARCH_CMPXCHG    1
+
+/* bug catcher for when unsupported size is used - won't link */
+extern void __cmpxchg_called_with_bad_pointer(void);
+/* we only need to support cmpxchg of a u32 on sparc */
+extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
+       default:
+               __cmpxchg_called_with_bad_pointer();
+               break;
+       }
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                             \
+({                                                                     \
+       __typeof__(*(ptr)) _o_ = (o);                                   \
+       __typeof__(*(ptr)) _n_ = (n);                                   \
+       (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,       \
+                       (unsigned long)_n_, sizeof(*(ptr)));            \
+})
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* __ARCH_SPARC_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h
new file mode 100644 (file)
index 0000000..b30eb37
--- /dev/null
@@ -0,0 +1,145 @@
+/* 64-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_CMPXCHG__
+#define __ARCH_SPARC64_CMPXCHG__
+
+static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
+{
+       unsigned long tmp1, tmp2;
+
+       __asm__ __volatile__(
+"      mov             %0, %1\n"
+"1:    lduw            [%4], %2\n"
+"      cas             [%4], %2, %0\n"
+"      cmp             %2, %0\n"
+"      bne,a,pn        %%icc, 1b\n"
+"       mov            %1, %0\n"
+       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+       : "0" (val), "r" (m)
+       : "cc", "memory");
+       return val;
+}
+
+static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
+{
+       unsigned long tmp1, tmp2;
+
+       __asm__ __volatile__(
+"      mov             %0, %1\n"
+"1:    ldx             [%4], %2\n"
+"      casx            [%4], %2, %0\n"
+"      cmp             %2, %0\n"
+"      bne,a,pn        %%xcc, 1b\n"
+"       mov            %1, %0\n"
+       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+       : "0" (val), "r" (m)
+       : "cc", "memory");
+       return val;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
+                                      int size)
+{
+       switch (size) {
+       case 4:
+               return xchg32(ptr, x);
+       case 8:
+               return xchg64(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *m, int old, int new)
+{
+       __asm__ __volatile__("cas [%2], %3, %0"
+                            : "=&r" (new)
+                            : "0" (new), "r" (m), "r" (old)
+                            : "memory");
+
+       return new;
+}
+
+static inline unsigned long
+__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
+{
+       __asm__ __volatile__("casx [%2], %3, %0"
+                            : "=&r" (new)
+                            : "0" (new), "r" (m), "r" (old)
+                            : "memory");
+
+       return new;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+               case 4:
+                       return __cmpxchg_u32(ptr, old, new);
+               case 8:
+                       return __cmpxchg_u64(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+       case 8: return __cmpxchg(ptr, old, new, size);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)                                     \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+  })
+
+#endif /* __ARCH_SPARC64_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h
new file mode 100644 (file)
index 0000000..4ca184d
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __ASM_CPU_TYPE_H
+#define __ASM_CPU_TYPE_H
+
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+  sun4        = 0x00,
+  sun4c       = 0x01,
+  sun4m       = 0x02,
+  sun4d       = 0x03,
+  sun4e       = 0x04,
+  sun4u       = 0x05, /* V8 ploos ploos */
+  sun_unknown = 0x06,
+  ap1000      = 0x07, /* almost a sun4m */
+  sparc_leon  = 0x08, /* Leon SoC */
+};
+
+#ifdef CONFIG_SPARC32
+extern enum sparc_cpu sparc_cpu_model;
+
+#define ARCH_SUN4C (sparc_cpu_model==sun4c)
+
+#define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
+
+#else
+
+#define sparc_cpu_model sun4u
+
+/* This cannot ever be a sun4c :) That's just history. */
+#define ARCH_SUN4C 0
+#endif
+
+#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/sparc/include/asm/exec.h b/arch/sparc/include/asm/exec.h
new file mode 100644 (file)
index 0000000..2e08588
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __SPARC_EXEC_H
+#define __SPARC_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __SPARC_EXEC_H */
index 7440915e86d8d970216a944b32765b1499a59192..698d9559feadddb486e977541e1288a28f08735c 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/idprom.h>
 #include <asm/machines.h>
 #include <asm/oplib.h>
index 444e7bea23bcbe81ac5005177f13e12e27192caf..4e899b0dabf79154f0ccc96a2ed1e0d7d230e04b 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/system.h>
 
 #define __futex_cas_op(insn, ret, oldval, uaddr, oparg)        \
        __asm__ __volatile__(                           \
index 2006e5d359dfb5f602ab004208ea60d610e15a6d..c1acbd891cbcce02c1ff1f54d4add3f690a3fb15 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/ioport.h>  /* struct resource */
 
 #include <asm/page.h>      /* IO address mapping routines need this */
-#include <asm/system.h>
 #include <asm-generic/pci_iomap.h>
 
 #define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
index 9481e5a6fa90e218ffa2124a0feef91ffd228b4a..09b0b88aeb2a422d5674b546768f36d413efc6c0 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 
 #include <asm/page.h>      /* IO address mapping routines need this */
-#include <asm/system.h>
 #include <asm/asi.h>
 #include <asm-generic/pci_iomap.h>
 
index 14848909e0dec49c7b5a7cc56b482bc9a068d26f..e414c06615c1a013bb2f867cb2bc21e27e8bbbd6 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/psr.h>
 
 extern void arch_local_irq_restore(unsigned long);
 extern unsigned long arch_local_irq_save(void);
index 666a73fef28dad76765a89eab95bb93c3eee232c..a97fd085cebec6d58a69b831e9284e3b3e9daeeb 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm-generic/mm_hooks.h>
 
index af755483e17dc7517ac9770f91325a81fe3ac8a8..6b947ee0f6aab592beb5cd172e12b7b0ea9deb8d 100644 (file)
@@ -79,7 +79,6 @@
 
 #include <linux/spinlock.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 extern spinlock_t ns87303_lock;
index 8d8720a8770de451e3e1911e189327caf03e4a2d..3332d2cba6c1d15fa39a1f6070cbc4055279e63d 100644 (file)
@@ -168,6 +168,29 @@ struct vcounter_struct {
   unsigned long long vcnt1;
 };
 
+#else /* !(__KERNEL__) */
+
+#ifndef CONFIG_SPARC32
+
+/* Performance counter register access. */
+#define read_pcr(__p)  __asm__ __volatile__("rd        %%pcr, %0" : "=r" (__p))
+#define write_pcr(__p) __asm__ __volatile__("wr        %0, 0x0, %%pcr" : : "r" (__p))
+#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
+
+/* Blackbird errata workaround.  See commentary in
+ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+ * for more information.
+ */
+#define write_pic(__p)                                         \
+       __asm__ __volatile__("ba,pt     %%xcc, 99f\n\t"         \
+                            " nop\n\t"                         \
+                            ".align    64\n"                   \
+                         "99:wr        %0, 0x0, %%pic\n\t"     \
+                            "rd        %%pic, %%g0" : : "r" (__p))
+#define reset_pic()    write_pic(0)
+
+#endif /* !CONFIG_SPARC32 */
+
 #endif /* !(__KERNEL__) */
 
 #endif /* !(PERF_COUNTER_API) */
index a790cc657476320831f9753ad0fd2aff9264ca0a..3d7101860e681ea645c2f338e18c0d80e3ad9fdf 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/vac-ops.h>
 #include <asm/oplib.h>
 #include <asm/btfixup.h>
-#include <asm/system.h>
+#include <asm/cpu_type.h>
 
 
 struct vm_area_struct;
index 38ebb2c601374a386192c061b50ea171c4f83373..6fa2f7980e6bc09fee78bb0dd34ecb0009ea68c1 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/types.h>
 #include <asm/spitfire.h>
 #include <asm/asi.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 
index dbfc1a34b3a23c6a4d17b39c46a6858d0eed8c78..3070f25ae90a3e235eaaf2373949226ea83acfb6 100644 (file)
@@ -9,35 +9,16 @@
 
 #if defined(__sparc__) && defined(__arch64__)
 /* sparc 64 bit */
-typedef unsigned long          __kernel_size_t;
-typedef long                   __kernel_ssize_t;
-typedef long                   __kernel_ptrdiff_t;
-typedef long                   __kernel_time_t;
-typedef long                   __kernel_clock_t;
-typedef int                    __kernel_pid_t;
-typedef int                    __kernel_ipc_pid_t;
-typedef unsigned int           __kernel_uid_t;
-typedef unsigned int           __kernel_gid_t;
-typedef unsigned long          __kernel_ino_t;
-typedef unsigned int           __kernel_mode_t;
 typedef unsigned int           __kernel_nlink_t;
-typedef int                    __kernel_daddr_t;
-typedef long                   __kernel_off_t;
-typedef char *                 __kernel_caddr_t;
-typedef unsigned short        __kernel_uid16_t;
-typedef unsigned short        __kernel_gid16_t;
-typedef int                    __kernel_clockid_t;
-typedef int                    __kernel_timer_t;
+#define __kernel_nlink_t __kernel_nlink_t
 
 typedef unsigned short                __kernel_old_uid_t;
 typedef unsigned short         __kernel_old_gid_t;
-typedef __kernel_uid_t        __kernel_uid32_t;
-typedef __kernel_gid_t        __kernel_gid32_t;
-
-typedef unsigned int          __kernel_old_dev_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
 
 /* Note this piece of asymmetry from the v9 ABI.  */
 typedef int                   __kernel_suseconds_t;
+#define __kernel_suseconds_t __kernel_suseconds_t
 
 #else
 /* sparc 32 bit */
@@ -45,109 +26,29 @@ typedef int                       __kernel_suseconds_t;
 typedef unsigned int           __kernel_size_t;
 typedef int                    __kernel_ssize_t;
 typedef long int               __kernel_ptrdiff_t;
-typedef long                   __kernel_time_t;
-typedef long                  __kernel_suseconds_t;
-typedef long                   __kernel_clock_t;
-typedef int                    __kernel_pid_t;
+#define __kernel_size_t __kernel_size_t
+
 typedef unsigned short         __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short         __kernel_uid_t;
 typedef unsigned short         __kernel_gid_t;
-typedef unsigned long          __kernel_ino_t;
+#define __kernel_uid_t __kernel_uid_t
+
 typedef unsigned short         __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef short                  __kernel_nlink_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef long                   __kernel_daddr_t;
-typedef long                   __kernel_off_t;
-typedef char *                 __kernel_caddr_t;
-typedef unsigned short        __kernel_uid16_t;
-typedef unsigned short        __kernel_gid16_t;
-typedef unsigned int          __kernel_uid32_t;
-typedef unsigned int          __kernel_gid32_t;
-typedef unsigned short        __kernel_old_uid_t;
-typedef unsigned short        __kernel_old_gid_t;
+#define __kernel_daddr_t __kernel_daddr_t
+
 typedef unsigned short        __kernel_old_dev_t;
-typedef int                    __kernel_clockid_t;
-typedef int                    __kernel_timer_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
 #endif /* defined(__sparc__) && defined(__arch64__) */
 
-#ifdef __GNUC__
-typedef long long              __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#ifdef __KERNEL__
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
-       unsigned long *tmp = p->fds_bits;
-       int i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-                       case 32:
-                         tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                         tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                         tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-                         tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                         tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
-                         tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
-                         tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
-                         tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
-                         return;
-                       case 16:
-                         tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                         tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                         tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-                         tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                         return;
-                       case 8:
-                         tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                         tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                         return;
-                       case 4:
-                         tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                         return;
-               }
-       }
-       i = __FDSET_LONGS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
+#include <asm-generic/posix_types.h>
 
-#endif /* __KERNEL__ */
 #endif /* __SPARC_POSIX_TYPES_H */
index 9da9646bf6c6b326ee6d6f47b1d60bd4dd970453..2fe99e66e760f0072dd6e1d66676016070baced6 100644 (file)
@@ -5,4 +5,7 @@
 #else
 #include <asm/processor_32.h>
 #endif
+
+#define nop()          __asm__ __volatile__ ("nop")
+
 #endif
index 59fcebb8f4405917ef60858251c5f81fd11c6b35..e713db249931fb3895cfcd842176187b8d948f71 100644 (file)
@@ -18,6 +18,9 @@
 #include <asm/ptrace.h>
 #include <asm/page.h>
 
+/* Don't hold the runqueue lock over context switch */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+
 /* The sparc has no problems with write protection */
 #define wp_works_ok 1
 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */
index c00c3b5c2806edfac2b2b7f44f79045ae1bfec01..ef8c7c068f53a3b3dfbaef79bcf9a5fa089b60f6 100644 (file)
@@ -98,6 +98,8 @@ struct sparc_trapf {
  */
 #ifndef __ASSEMBLY__
 
+#include <linux/types.h>
+
 struct pt_regs {
        unsigned long psr;
        unsigned long pc;
@@ -163,7 +165,6 @@ struct sparc_stackf {
 #ifdef __KERNEL__
 
 #include <linux/threads.h>
-#include <asm/system.h>
 
 static inline int pt_regs_trap_type(struct pt_regs *regs)
 {
@@ -240,8 +241,6 @@ extern unsigned long profile_pc(struct pt_regs *);
 
 #ifdef __KERNEL__
 
-#include <asm/system.h>
-
 static inline bool pt_regs_is_syscall(struct pt_regs *regs)
 {
        return (regs->psr & PSR_SYSCALL);
index 64718ba26434bb490e2c27a719d5a20f0ea76946..00497abec996aa1c001cacd35f1444f251b26cae 100644 (file)
 
 #ifdef __KERNEL__
 
+extern char reboot_command[];
+
 #ifdef CONFIG_SPARC32
 /* The CPU that was used for booting
  * Only sun4d + leon may have boot_cpu_id != 0
  */
 extern unsigned char boot_cpu_id;
 extern unsigned char boot_cpu_id4;
+
+extern unsigned long empty_bad_page;
+extern unsigned long empty_bad_page_table;
+extern unsigned long empty_zero_page;
+
+extern int serial_console;
+static inline int con_is_present(void)
+{
+       return serial_console ? 0 : 1;
+}
 #endif
 
+extern void sun_do_break(void);
+extern int stop_a_enabled;
+extern int scons_pwroff;
+
 #endif /* __KERNEL__ */
 
 #endif /* _SPARC_SETUP_H */
diff --git a/arch/sparc/include/asm/switch_to.h b/arch/sparc/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..2dc4fa5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_SWITCH_TO_H
+#define ___ASM_SPARC_SWITCH_TO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/switch_to_64.h>
+#else
+#include <asm/switch_to_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/switch_to_32.h b/arch/sparc/include/asm/switch_to_32.h
new file mode 100644 (file)
index 0000000..e32e82b
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __SPARC_SWITCH_TO_H
+#define __SPARC_SWITCH_TO_H
+
+#include <asm/smp.h>
+
+extern struct thread_info *current_set[NR_CPUS];
+
+/*
+ * Flush windows so that the VM switch which follows
+ * would not pull the stack from under us.
+ *
+ * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
+ * XXX WTF is the above comment? Found in late teen 2.4.x.
+ */
+#ifdef CONFIG_SMP
+#define SWITCH_ENTER(prv) \
+       do {                    \
+       if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
+               put_psr(get_psr() | PSR_EF); \
+               fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
+                      &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
+               clear_tsk_thread_flag(prv, TIF_USEDFPU); \
+               (prv)->thread.kregs->psr &= ~PSR_EF; \
+       } \
+       } while(0)
+
+#define SWITCH_DO_LAZY_FPU(next)       /* */
+#else
+#define SWITCH_ENTER(prv)              /* */
+#define SWITCH_DO_LAZY_FPU(nxt)        \
+       do {                    \
+       if (last_task_used_math != (nxt))               \
+               (nxt)->thread.kregs->psr&=~PSR_EF;      \
+       } while(0)
+#endif
+
+#define prepare_arch_switch(next) do { \
+       __asm__ __volatile__( \
+       ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
+       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+       "save %sp, -0x40, %sp\n\t" \
+       "restore; restore; restore; restore; restore; restore; restore"); \
+} while(0)
+
+       /* Much care has gone into this code, do not touch it.
+        *
+        * We need to loadup regs l0/l1 for the newly forked child
+        * case because the trap return path relies on those registers
+        * holding certain values, gcc is told that they are clobbered.
+        * Gcc needs registers for 3 values in and 1 value out, so we
+        * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
+        *
+        * Hey Dave, that do not touch sign is too much of an incentive
+        * - Anton & Pete
+        */
+#define switch_to(prev, next, last) do {                                               \
+       SWITCH_ENTER(prev);                                                             \
+       SWITCH_DO_LAZY_FPU(next);                                                       \
+       cpumask_set_cpu(smp_processor_id(), mm_cpumask(next->active_mm));               \
+       __asm__ __volatile__(                                                           \
+       "sethi  %%hi(here - 0x8), %%o7\n\t"                                             \
+       "mov    %%g6, %%g3\n\t"                                                         \
+       "or     %%o7, %%lo(here - 0x8), %%o7\n\t"                                       \
+       "rd     %%psr, %%g4\n\t"                                                        \
+       "std    %%sp, [%%g6 + %4]\n\t"                                                  \
+       "rd     %%wim, %%g5\n\t"                                                        \
+       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
+       "nop\n\t"                                                                       \
+       "std    %%g4, [%%g6 + %3]\n\t"                                                  \
+       "ldd    [%2 + %3], %%g4\n\t"                                                    \
+       "mov    %2, %%g6\n\t"                                                           \
+       ".globl patchme_store_new_current\n"                                            \
+"patchme_store_new_current:\n\t"                                                       \
+       "st     %2, [%1]\n\t"                                                           \
+       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
+       "nop\n\t"                                                                       \
+       "nop\n\t"                                                                       \
+       "nop\n\t"       /* LEON needs all 3 nops: load to %sp depends on CWP. */                \
+       "ldd    [%%g6 + %4], %%sp\n\t"                                                  \
+       "wr     %%g5, 0x0, %%wim\n\t"                                                   \
+       "ldd    [%%sp + 0x00], %%l0\n\t"                                                \
+       "ldd    [%%sp + 0x38], %%i6\n\t"                                                \
+       "wr     %%g4, 0x0, %%psr\n\t"                                                   \
+       "nop\n\t"                                                                       \
+       "nop\n\t"                                                                       \
+       "jmpl   %%o7 + 0x8, %%g0\n\t"                                                   \
+       " ld    [%%g3 + %5], %0\n\t"                                                    \
+       "here:\n"                                                                       \
+        : "=&r" (last)                                                                 \
+        : "r" (&(current_set[hard_smp_processor_id()])),       \
+         "r" (task_thread_info(next)),                         \
+         "i" (TI_KPSR),                                        \
+         "i" (TI_KSP),                                         \
+         "i" (TI_TASK)                                         \
+       :       "g1", "g2", "g3", "g4", "g5",       "g7",       \
+         "l0", "l1",       "l3", "l4", "l5", "l6", "l7",       \
+         "i0", "i1", "i2", "i3", "i4", "i5",                   \
+         "o0", "o1", "o2", "o3",                   "o7");      \
+       } while(0)
+
+extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+                  void *fpqueue, unsigned long *fpqdepth);
+extern void synchronize_user_stack(void);
+
+#endif /* __SPARC_SWITCH_TO_H */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
new file mode 100644 (file)
index 0000000..7923c4a
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __SPARC64_SWITCH_TO_64_H
+#define __SPARC64_SWITCH_TO_64_H
+
+#include <asm/visasm.h>
+
+#define prepare_arch_switch(next)              \
+do {                                           \
+       flushw_all();                           \
+} while (0)
+
+       /* See what happens when you design the chip correctly?
+        *
+        * We tell gcc we clobber all non-fixed-usage registers except
+        * for l0/l1.  It will use one for 'next' and the other to hold
+        * the output value of 'last'.  'next' is not referenced again
+        * past the invocation of switch_to in the scheduler, so we need
+        * not preserve it's value.  Hairy, but it lets us remove 2 loads
+        * and 2 stores in this critical code path.  -DaveM
+        */
+#define switch_to(prev, next, last)                                    \
+do {   flush_tlb_pending();                                            \
+       save_and_clear_fpu();                                           \
+       /* If you are tempted to conditionalize the following */        \
+       /* so that ASI is only written if it changes, think again. */   \
+       __asm__ __volatile__("wr %%g0, %0, %%asi"                       \
+       : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
+       trap_block[current_thread_info()->cpu].thread =                 \
+               task_thread_info(next);                                 \
+       __asm__ __volatile__(                                           \
+       "mov    %%g4, %%g7\n\t"                                         \
+       "stx    %%i6, [%%sp + 2047 + 0x70]\n\t"                         \
+       "stx    %%i7, [%%sp + 2047 + 0x78]\n\t"                         \
+       "rdpr   %%wstate, %%o5\n\t"                                     \
+       "stx    %%o6, [%%g6 + %6]\n\t"                                  \
+       "stb    %%o5, [%%g6 + %5]\n\t"                                  \
+       "rdpr   %%cwp, %%o5\n\t"                                        \
+       "stb    %%o5, [%%g6 + %8]\n\t"                                  \
+       "wrpr   %%g0, 15, %%pil\n\t"                                    \
+       "mov    %4, %%g6\n\t"                                           \
+       "ldub   [%4 + %8], %%g1\n\t"                                    \
+       "wrpr   %%g1, %%cwp\n\t"                                        \
+       "ldx    [%%g6 + %6], %%o6\n\t"                                  \
+       "ldub   [%%g6 + %5], %%o5\n\t"                                  \
+       "ldub   [%%g6 + %7], %%o7\n\t"                                  \
+       "wrpr   %%o5, 0x0, %%wstate\n\t"                                \
+       "ldx    [%%sp + 2047 + 0x70], %%i6\n\t"                         \
+       "ldx    [%%sp + 2047 + 0x78], %%i7\n\t"                         \
+       "ldx    [%%g6 + %9], %%g4\n\t"                                  \
+       "wrpr   %%g0, 14, %%pil\n\t"                                    \
+       "brz,pt %%o7, switch_to_pc\n\t"                                 \
+       " mov   %%g7, %0\n\t"                                           \
+       "sethi  %%hi(ret_from_syscall), %%g1\n\t"                       \
+       "jmpl   %%g1 + %%lo(ret_from_syscall), %%g0\n\t"                \
+       " nop\n\t"                                                      \
+       ".globl switch_to_pc\n\t"                                       \
+       "switch_to_pc:\n\t"                                             \
+       : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
+         "=r" (__local_per_cpu_offset)                                 \
+       : "0" (task_thread_info(next)),                                 \
+         "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
+         "i" (TI_CWP), "i" (TI_TASK)                                   \
+       : "cc",                                                         \
+               "g1", "g2", "g3",                   "g7",               \
+               "l1", "l2", "l3", "l4", "l5", "l6", "l7",               \
+         "i0", "i1", "i2", "i3", "i4", "i5",                           \
+         "o0", "o1", "o2", "o3", "o4", "o5",       "o7");              \
+} while(0)
+
+extern void synchronize_user_stack(void);
+extern void fault_in_user_windows(void);
+
+#endif /* __SPARC64_SWITCH_TO_64_H */
diff --git a/arch/sparc/include/asm/system.h b/arch/sparc/include/asm/system.h
deleted file mode 100644 (file)
index 7944a7c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ___ASM_SPARC_SYSTEM_H
-#define ___ASM_SPARC_SYSTEM_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/system_64.h>
-#else
-#include <asm/system_32.h>
-#endif
-#endif
diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h
deleted file mode 100644 (file)
index aba1609..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-#ifndef __SPARC_SYSTEM_H
-#define __SPARC_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/threads.h>     /* NR_CPUS */
-#include <linux/thread_info.h>
-
-#include <asm/page.h>
-#include <asm/psr.h>
-#include <asm/ptrace.h>
-#include <asm/btfixup.h>
-#include <asm/smp.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/irqflags.h>
-
-/*
- * Sparc (general) CPU types
- */
-enum sparc_cpu {
-  sun4        = 0x00,
-  sun4c       = 0x01,
-  sun4m       = 0x02,
-  sun4d       = 0x03,
-  sun4e       = 0x04,
-  sun4u       = 0x05, /* V8 ploos ploos */
-  sun_unknown = 0x06,
-  ap1000      = 0x07, /* almost a sun4m */
-  sparc_leon  = 0x08, /* Leon SoC */
-};
-
-/* Really, userland should not be looking at any of this... */
-#ifdef __KERNEL__
-
-extern enum sparc_cpu sparc_cpu_model;
-
-#define ARCH_SUN4C (sparc_cpu_model==sun4c)
-
-#define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
-
-extern char reboot_command[];
-
-extern struct thread_info *current_set[NR_CPUS];
-
-extern unsigned long empty_bad_page;
-extern unsigned long empty_bad_page_table;
-extern unsigned long empty_zero_page;
-
-extern void sun_do_break(void);
-extern int serial_console;
-extern int stop_a_enabled;
-extern int scons_pwroff;
-
-static inline int con_is_present(void)
-{
-       return serial_console ? 0 : 1;
-}
-
-/* When a context switch happens we must flush all user windows so that
- * the windows of the current process are flushed onto its stack. This
- * way the windows are all clean for the next process and the stack
- * frames are up to date.
- */
-extern void flush_user_windows(void);
-extern void kill_user_windows(void);
-extern void synchronize_user_stack(void);
-extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
-                  void *fpqueue, unsigned long *fpqdepth);
-
-#ifdef CONFIG_SMP
-#define SWITCH_ENTER(prv) \
-       do {                    \
-       if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
-               put_psr(get_psr() | PSR_EF); \
-               fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
-                      &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
-               clear_tsk_thread_flag(prv, TIF_USEDFPU); \
-               (prv)->thread.kregs->psr &= ~PSR_EF; \
-       } \
-       } while(0)
-
-#define SWITCH_DO_LAZY_FPU(next)       /* */
-#else
-#define SWITCH_ENTER(prv)              /* */
-#define SWITCH_DO_LAZY_FPU(nxt)        \
-       do {                    \
-       if (last_task_used_math != (nxt))               \
-               (nxt)->thread.kregs->psr&=~PSR_EF;      \
-       } while(0)
-#endif
-
-extern void flushw_all(void);
-
-/*
- * Flush windows so that the VM switch which follows
- * would not pull the stack from under us.
- *
- * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
- * XXX WTF is the above comment? Found in late teen 2.4.x.
- */
-#define prepare_arch_switch(next) do { \
-       __asm__ __volatile__( \
-       ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
-       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
-       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
-       "save %sp, -0x40, %sp\n\t" \
-       "restore; restore; restore; restore; restore; restore; restore"); \
-} while(0)
-
-       /* Much care has gone into this code, do not touch it.
-        *
-        * We need to loadup regs l0/l1 for the newly forked child
-        * case because the trap return path relies on those registers
-        * holding certain values, gcc is told that they are clobbered.
-        * Gcc needs registers for 3 values in and 1 value out, so we
-        * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
-        *
-        * Hey Dave, that do not touch sign is too much of an incentive
-        * - Anton & Pete
-        */
-#define switch_to(prev, next, last) do {                                               \
-       SWITCH_ENTER(prev);                                                             \
-       SWITCH_DO_LAZY_FPU(next);                                                       \
-       cpumask_set_cpu(smp_processor_id(), mm_cpumask(next->active_mm));               \
-       __asm__ __volatile__(                                                           \
-       "sethi  %%hi(here - 0x8), %%o7\n\t"                                             \
-       "mov    %%g6, %%g3\n\t"                                                         \
-       "or     %%o7, %%lo(here - 0x8), %%o7\n\t"                                       \
-       "rd     %%psr, %%g4\n\t"                                                        \
-       "std    %%sp, [%%g6 + %4]\n\t"                                                  \
-       "rd     %%wim, %%g5\n\t"                                                        \
-       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
-       "nop\n\t"                                                                       \
-       "std    %%g4, [%%g6 + %3]\n\t"                                                  \
-       "ldd    [%2 + %3], %%g4\n\t"                                                    \
-       "mov    %2, %%g6\n\t"                                                           \
-       ".globl patchme_store_new_current\n"                                            \
-"patchme_store_new_current:\n\t"                                                       \
-       "st     %2, [%1]\n\t"                                                           \
-       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
-       "nop\n\t"                                                                       \
-       "nop\n\t"                                                                       \
-       "nop\n\t"       /* LEON needs all 3 nops: load to %sp depends on CWP. */                \
-       "ldd    [%%g6 + %4], %%sp\n\t"                                                  \
-       "wr     %%g5, 0x0, %%wim\n\t"                                                   \
-       "ldd    [%%sp + 0x00], %%l0\n\t"                                                \
-       "ldd    [%%sp + 0x38], %%i6\n\t"                                                \
-       "wr     %%g4, 0x0, %%psr\n\t"                                                   \
-       "nop\n\t"                                                                       \
-       "nop\n\t"                                                                       \
-       "jmpl   %%o7 + 0x8, %%g0\n\t"                                                   \
-       " ld    [%%g3 + %5], %0\n\t"                                                    \
-       "here:\n"                                                                       \
-        : "=&r" (last)                                                                 \
-        : "r" (&(current_set[hard_smp_processor_id()])),       \
-         "r" (task_thread_info(next)),                         \
-         "i" (TI_KPSR),                                        \
-         "i" (TI_KSP),                                         \
-         "i" (TI_TASK)                                         \
-       :       "g1", "g2", "g3", "g4", "g5",       "g7",       \
-         "l0", "l1",       "l3", "l4", "l5", "l6", "l7",       \
-         "i0", "i1", "i2", "i3", "i4", "i5",                   \
-         "o0", "o1", "o2", "o3",                   "o7");      \
-       } while(0)
-
-/* XXX Change this if we ever use a PSO mode kernel. */
-#define mb()   __asm__ __volatile__ ("" : : : "memory")
-#define rmb()  mb()
-#define wmb()  mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
-#define smp_mb()       __asm__ __volatile__("":::"memory")
-#define smp_rmb()      __asm__ __volatile__("":::"memory")
-#define smp_wmb()      __asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends()     do { } while(0)
-
-#define nop() __asm__ __volatile__ ("nop")
-
-/* This has special calling conventions */
-#ifndef CONFIG_SMP
-BTFIXUPDEF_CALL(void, ___xchg32, void)
-#endif
-
-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
-{
-#ifdef CONFIG_SMP
-       __asm__ __volatile__("swap [%2], %0"
-                            : "=&r" (val)
-                            : "0" (val), "r" (m)
-                            : "memory");
-       return val;
-#else
-       register unsigned long *ptr asm("g1");
-       register unsigned long ret asm("g2");
-
-       ptr = (unsigned long *) m;
-       ret = val;
-
-       /* Note: this is magic and the nop there is
-          really needed. */
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___f____xchg32\n\t"
-       " nop\n\t"
-       : "=&r" (ret)
-       : "0" (ret), "r" (ptr)
-       : "g3", "g4", "g7", "memory", "cc");
-
-       return ret;
-#endif
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
-{
-       switch (size) {
-       case 4:
-               return xchg_u32(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-/* Emulate cmpxchg() the same way we emulate atomics,
- * by hashing the object address and indexing into an array
- * of spinlocks to get a bit of performance...
- *
- * See arch/sparc/lib/atomic32.c for implementation.
- *
- * Cribbed from <asm-parisc/atomic.h>
- */
-#define __HAVE_ARCH_CMPXCHG    1
-
-/* bug catcher for when unsupported size is used - won't link */
-extern void __cmpxchg_called_with_bad_pointer(void);
-/* we only need to support cmpxchg of a u32 on sparc */
-extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
-
-/* don't worry...optimizer will get rid of most of this */
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
-       default:
-               __cmpxchg_called_with_bad_pointer();
-               break;
-       }
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                             \
-({                                                                     \
-       __typeof__(*(ptr)) _o_ = (o);                                   \
-       __typeof__(*(ptr)) _n_ = (n);                                   \
-       (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,       \
-                       (unsigned long)_n_, sizeof(*(ptr)));            \
-})
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* !(__SPARC_SYSTEM_H) */
diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h
deleted file mode 100644 (file)
index 10bcabc..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-#ifndef __SPARC64_SYSTEM_H
-#define __SPARC64_SYSTEM_H
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/visasm.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/irqflags.h>
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * Sparc (general) CPU types
- */
-enum sparc_cpu {
-  sun4        = 0x00,
-  sun4c       = 0x01,
-  sun4m       = 0x02,
-  sun4d       = 0x03,
-  sun4e       = 0x04,
-  sun4u       = 0x05, /* V8 ploos ploos */
-  sun_unknown = 0x06,
-  ap1000      = 0x07, /* almost a sun4m */
-};
-
-#define sparc_cpu_model sun4u
-
-/* This cannot ever be a sun4c :) That's just history. */
-#define ARCH_SUN4C 0
-
-extern char reboot_command[];
-
-/* These are here in an effort to more fully work around Spitfire Errata
- * #51.  Essentially, if a memory barrier occurs soon after a mispredicted
- * branch, the chip can stop executing instructions until a trap occurs.
- * Therefore, if interrupts are disabled, the chip can hang forever.
- *
- * It used to be believed that the memory barrier had to be right in the
- * delay slot, but a case has been traced recently wherein the memory barrier
- * was one instruction after the branch delay slot and the chip still hung.
- * The offending sequence was the following in sym_wakeup_done() of the
- * sym53c8xx_2 driver:
- *
- *     call    sym_ccb_from_dsa, 0
- *      movge  %icc, 0, %l0
- *     brz,pn  %o0, .LL1303
- *      mov    %o0, %l2
- *     membar  #LoadLoad
- *
- * The branch has to be mispredicted for the bug to occur.  Therefore, we put
- * the memory barrier explicitly into a "branch always, predicted taken"
- * delay slot to avoid the problem case.
- */
-#define membar_safe(type) \
-do {   __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
-                            " membar   " type "\n" \
-                            "1:\n" \
-                            : : : "memory"); \
-} while (0)
-
-/* The kernel always executes in TSO memory model these days,
- * and furthermore most sparc64 chips implement more stringent
- * memory ordering than required by the specifications.
- */
-#define mb()   membar_safe("#StoreLoad")
-#define rmb()  __asm__ __volatile__("":::"memory")
-#define wmb()  __asm__ __volatile__("":::"memory")
-
-#endif
-
-#define nop()          __asm__ __volatile__ ("nop")
-
-#define read_barrier_depends()         do { } while(0)
-#define set_mb(__var, __value) \
-       do { __var = __value; membar_safe("#StoreLoad"); } while(0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#else
-#define smp_mb()       __asm__ __volatile__("":::"memory")
-#define smp_rmb()      __asm__ __volatile__("":::"memory")
-#define smp_wmb()      __asm__ __volatile__("":::"memory")
-#endif
-
-#define smp_read_barrier_depends()     do { } while(0)
-
-#define flushi(addr)   __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
-
-#define flushw_all()   __asm__ __volatile__("flushw")
-
-/* Performance counter register access. */
-#define read_pcr(__p)  __asm__ __volatile__("rd        %%pcr, %0" : "=r" (__p))
-#define write_pcr(__p) __asm__ __volatile__("wr        %0, 0x0, %%pcr" : : "r" (__p))
-#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-
-/* Blackbird errata workaround.  See commentary in
- * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
- * for more information.
- */
-#define write_pic(__p)                                         \
-       __asm__ __volatile__("ba,pt     %%xcc, 99f\n\t"         \
-                            " nop\n\t"                         \
-                            ".align    64\n"                   \
-                         "99:wr        %0, 0x0, %%pic\n\t"     \
-                            "rd        %%pic, %%g0" : : "r" (__p))
-#define reset_pic()    write_pic(0)
-
-#ifndef __ASSEMBLY__
-
-extern void sun_do_break(void);
-extern int stop_a_enabled;
-extern int scons_pwroff;
-
-extern void fault_in_user_windows(void);
-extern void synchronize_user_stack(void);
-
-extern void __flushw_user(void);
-#define flushw_user() __flushw_user()
-
-#define flush_user_windows flushw_user
-#define flush_register_windows flushw_all
-
-/* Don't hold the runqueue lock over context switch */
-#define __ARCH_WANT_UNLOCKED_CTXSW
-#define prepare_arch_switch(next)              \
-do {                                           \
-       flushw_all();                           \
-} while (0)
-
-       /* See what happens when you design the chip correctly?
-        *
-        * We tell gcc we clobber all non-fixed-usage registers except
-        * for l0/l1.  It will use one for 'next' and the other to hold
-        * the output value of 'last'.  'next' is not referenced again
-        * past the invocation of switch_to in the scheduler, so we need
-        * not preserve it's value.  Hairy, but it lets us remove 2 loads
-        * and 2 stores in this critical code path.  -DaveM
-        */
-#define switch_to(prev, next, last)                                    \
-do {   flush_tlb_pending();                                            \
-       save_and_clear_fpu();                                           \
-       /* If you are tempted to conditionalize the following */        \
-       /* so that ASI is only written if it changes, think again. */   \
-       __asm__ __volatile__("wr %%g0, %0, %%asi"                       \
-       : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
-       trap_block[current_thread_info()->cpu].thread =                 \
-               task_thread_info(next);                                 \
-       __asm__ __volatile__(                                           \
-       "mov    %%g4, %%g7\n\t"                                         \
-       "stx    %%i6, [%%sp + 2047 + 0x70]\n\t"                         \
-       "stx    %%i7, [%%sp + 2047 + 0x78]\n\t"                         \
-       "rdpr   %%wstate, %%o5\n\t"                                     \
-       "stx    %%o6, [%%g6 + %6]\n\t"                                  \
-       "stb    %%o5, [%%g6 + %5]\n\t"                                  \
-       "rdpr   %%cwp, %%o5\n\t"                                        \
-       "stb    %%o5, [%%g6 + %8]\n\t"                                  \
-       "wrpr   %%g0, 15, %%pil\n\t"                                    \
-       "mov    %4, %%g6\n\t"                                           \
-       "ldub   [%4 + %8], %%g1\n\t"                                    \
-       "wrpr   %%g1, %%cwp\n\t"                                        \
-       "ldx    [%%g6 + %6], %%o6\n\t"                                  \
-       "ldub   [%%g6 + %5], %%o5\n\t"                                  \
-       "ldub   [%%g6 + %7], %%o7\n\t"                                  \
-       "wrpr   %%o5, 0x0, %%wstate\n\t"                                \
-       "ldx    [%%sp + 2047 + 0x70], %%i6\n\t"                         \
-       "ldx    [%%sp + 2047 + 0x78], %%i7\n\t"                         \
-       "ldx    [%%g6 + %9], %%g4\n\t"                                  \
-       "wrpr   %%g0, 14, %%pil\n\t"                                    \
-       "brz,pt %%o7, switch_to_pc\n\t"                                 \
-       " mov   %%g7, %0\n\t"                                           \
-       "sethi  %%hi(ret_from_syscall), %%g1\n\t"                       \
-       "jmpl   %%g1 + %%lo(ret_from_syscall), %%g0\n\t"                \
-       " nop\n\t"                                                      \
-       ".globl switch_to_pc\n\t"                                       \
-       "switch_to_pc:\n\t"                                             \
-       : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
-         "=r" (__local_per_cpu_offset)                                 \
-       : "0" (task_thread_info(next)),                                 \
-         "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
-         "i" (TI_CWP), "i" (TI_TASK)                                   \
-       : "cc",                                                         \
-               "g1", "g2", "g3",                   "g7",               \
-               "l1", "l2", "l3", "l4", "l5", "l6", "l7",               \
-         "i0", "i1", "i2", "i3", "i4", "i5",                           \
-         "o0", "o1", "o2", "o3", "o4", "o5",       "o7");              \
-} while(0)
-
-static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
-{
-       unsigned long tmp1, tmp2;
-
-       __asm__ __volatile__(
-"      mov             %0, %1\n"
-"1:    lduw            [%4], %2\n"
-"      cas             [%4], %2, %0\n"
-"      cmp             %2, %0\n"
-"      bne,a,pn        %%icc, 1b\n"
-"       mov            %1, %0\n"
-       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
-       : "0" (val), "r" (m)
-       : "cc", "memory");
-       return val;
-}
-
-static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
-{
-       unsigned long tmp1, tmp2;
-
-       __asm__ __volatile__(
-"      mov             %0, %1\n"
-"1:    ldx             [%4], %2\n"
-"      casx            [%4], %2, %0\n"
-"      cmp             %2, %0\n"
-"      bne,a,pn        %%xcc, 1b\n"
-"       mov            %1, %0\n"
-       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
-       : "0" (val), "r" (m)
-       : "cc", "memory");
-       return val;
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
-                                      int size)
-{
-       switch (size) {
-       case 4:
-               return xchg32(ptr, x);
-       case 8:
-               return xchg64(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long
-__cmpxchg_u32(volatile int *m, int old, int new)
-{
-       __asm__ __volatile__("cas [%2], %3, %0"
-                            : "=&r" (new)
-                            : "0" (new), "r" (m), "r" (old)
-                            : "memory");
-
-       return new;
-}
-
-static inline unsigned long
-__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
-{
-       __asm__ __volatile__("casx [%2], %3, %0"
-                            : "=&r" (new)
-                            : "0" (new), "r" (m), "r" (old)
-                            : "memory");
-
-       return new;
-}
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-               case 4:
-                       return __cmpxchg_u32(ptr, old, new);
-               case 8:
-                       return __cmpxchg_u64(ptr, old, new);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)                                                \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-       case 8: return __cmpxchg(ptr, old, new, size);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-
-#endif /* !(__ASSEMBLY__) */
-
-#define arch_align_stack(x) (x)
-
-#endif /* !(__SPARC64_SYSTEM_H) */
index 2ec030ef38102307911b405ce62e04c3e4470152..1a91e11dd10493a0c7bbce0316276e25ffa2e14e 100644 (file)
@@ -8,12 +8,13 @@
 #ifndef _SPARC_TIMER_H
 #define _SPARC_TIMER_H
 
-#include <asm/system.h>  /* For SUN4M_NCPUS */
+#include <asm/cpu_type.h>  /* For SUN4M_NCPUS */
 #include <asm/btfixup.h>
 
 extern __volatile__ unsigned int *master_l10_counter;
 
 /* FIXME: Make do_[gs]ettimeofday btfixup calls */
+struct timespec;
 BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv)
 #define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv)
 
index 3e1449f077981efe818301bc9bef530969f65719..a1091afb8831f97b5b214bf278d043143b4b9764 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/string.h>
 #include <linux/thread_info.h>
 #include <asm/asi.h>
-#include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm-generic/uaccess-unaligned.h>
 #endif
index 9d83d3bcb494b44e3620f4942934e832035450a5..432afa83886137a89bcd6fa66911922addfa50d3 100644 (file)
@@ -284,6 +284,7 @@ struct vio_dev {
 };
 
 struct vio_driver {
+       const char                      *name;
        struct list_head                node;
        const struct vio_device_id      *id_table;
        int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
@@ -371,7 +372,13 @@ do {       if (vio->debug & VIO_DEBUG_##TYPE) \
                       vio->vdev->channel_id, ## a); \
 } while (0)
 
-extern int vio_register_driver(struct vio_driver *drv);
+extern int __vio_register_driver(struct vio_driver *drv, struct module *owner,
+                                const char *mod_name);
+/*
+ * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
+ */
+#define vio_register_driver(driver)            \
+       __vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
 extern void vio_unregister_driver(struct vio_driver *drv);
 
 static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
index f7ea8f0327199ebc8a22e9f4fe663a1794410b7c..56d0f52c3e62e5d675cc7f5f28089266f2b13985 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/io.h>
 #include <asm/auxio.h>
 #include <asm/string.h>                /* memset(), Linux has no bzero() */
+#include <asm/cpu_type.h>
 
 /* Probe and map in the Auxiliary I/O register */
 
index 113c052c30432ed7cd1316b5e46d9e9ffa5bcfa1..6b2f56a6f8af6206a519eddb0f391d263284161f 100644 (file)
@@ -17,8 +17,8 @@
 #include <asm/oplib.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/cpudata.h>
+#include <asm/cpu_type.h>
 
 extern void clock_stop_probe(void); /* tadpole.c */
 extern void sun4c_probe_memerr_reg(void);
index 381edcd5bc2946471e2c47e4f73a607272d25c09..fea13c7b1aeeddcf206217c935a1b044ae96e215 100644 (file)
@@ -1244,10 +1244,7 @@ static struct vio_driver ds_driver = {
        .id_table       = ds_match,
        .probe          = ds_probe,
        .remove         = ds_remove,
-       .driver         = {
-               .name   = "ds",
-               .owner  = THIS_MODULE,
-       }
+       .name           = "ds",
 };
 
 static int __init ds_init(void)
index 42851122bbd9c35b184a22454540fbc182e1c7e9..5a021dd2f854f0fe1abd37bd02593f7dd514a32c 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/btfixup.h>
+#include <asm/cpu_type.h>
 
 struct irq_bucket {
         struct irq_bucket *next;
index d45b710ea7e429eb86c5fbcb1c7fb55c5a2a1f6a..dff2c3d7d370cc7464663da148ccc937ce99fa94 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/iommu.h>
index 539243b236fa4c1400ed827aef7eb264b5c2693b..2e424a576a36e7eb751a177446e8da05bdcfbd6e 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/kdebug.h>
 #include <asm/ptrace.h>
 #include <asm/irq.h>
+#include <asm/cacheflush.h>
 
 extern unsigned long trapbase;
 
index e5519870c3d9ab43b516c5994568af974664d616..276359e1ff56505c2b15a1dd364565963f75935d 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/processor.h>
 #include <asm/spitfire.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 
index 6ce1021d487ca809f57434fae177ae6410690661..f7db516b07d815fc0d5503d2dd39330377f17f43 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/mm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "kernel.h"
index c76fe0b5bd94aa09df0a206ed2ddd385eeac5c8d..eb1c1f010a4797e629e370968e3980f887c92837 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/perf_event.h>
 #include <asm/ptrace.h>
 #include <asm/pcr.h>
+#include <asm/perfctr.h>
 
 #include "kstack.h"
 
index a24072a49270ea17e2cb5ee1a3da57eafd1e8352..0ce0dd2332aac60802a0cce15366e2b0158c2d36 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/pcr.h>
 #include <asm/nmi.h>
 #include <asm/spitfire.h>
+#include <asm/perfctr.h>
 
 /* This code is shared between various users of the performance
  * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
index 8e16a4a21582073bd1f2edc21d33efafb8f7e2fa..28559ce5eeb523ecd81ee00879b68ef540ee39bc 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/atomic.h>
 #include <asm/nmi.h>
 #include <asm/pcr.h>
+#include <asm/perfctr.h>
+#include <asm/cacheflush.h>
 
 #include "kernel.h"
 #include "kstack.h"
index 935fdbcd88c20b5d64a9c965e102e47edfe1048a..efa07542e85f22ab48de546104c07a91b4cdcfcd 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/auxio.h>
 #include <asm/oplib.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
@@ -38,6 +37,7 @@
 #include <asm/elf.h>
 #include <asm/prom.h>
 #include <asm/unistd.h>
+#include <asm/setup.h>
 
 /* 
  * Power management idle function 
index 06b5b5fc20c78f2e859875b79a372fec3e76f7e2..aff0c72fac0999b70a4407179aad99eebfe84c29 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/nmi.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 27b9e93d012168e8084d2af5e9b111d458e47ba8..896ba7c5cd8eb9c6433d6b51966b93b474542e9b 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/tracehook.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 
 /* #define ALLOW_INIT_TRACING */
 
index 9388844cd88c5afa47f3a24027019a96d11895ba..6f97c07679950aa730cb79f6c9810d9f0fb50bda 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/asi.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/psrcompat.h>
 #include <asm/visasm.h>
index 006a42dd200700430b6befc4b5844ac63df199ca..eba7d918162a55c2b331d016900ed08426ba1c71 100644 (file)
@@ -7,9 +7,9 @@
 #include <linux/export.h>
 #include <linux/pm.h>
 
-#include <asm/system.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 /* sysctl - toggle power-off restriction for serial console
  * systems in machine_power_off()
index ffb883ddd0f0109d80748fb524a930828499f0ac..d444468b27f67c42e0c83058cb06c52a69584271 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kdebug.h>
 #include <linux/export.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/oplib.h>
@@ -46,6 +45,7 @@
 #include <asm/machines.h>
 #include <asm/cpudata.h>
 #include <asm/setup.h>
+#include <asm/cacheflush.h>
 
 #include "kernel.h"
 
index a854a1c240ffe1eff016a3324ecfccd1dd63ce4c..1414d16712b272fd966bb03d94fa810f53425f19 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/initrd.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/oplib.h>
@@ -49,6 +48,7 @@
 #include <asm/btext.h>
 #include <asm/elf.h>
 #include <asm/mdesc.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_IP_PNP
 #include <net/ipconfig.h>
index c8f5b50db89ceda3be69c8d5cc17d1b16476d0f5..948700fb90365d3c54811d24577a841542ad757f 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/fpumacro.h>
 #include <asm/visasm.h>
 #include <asm/compat_signal.h>
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index 7bb71b6fbd2052185943ada79384228a598f8739..1e750e415d7add86854f0c522c1148898d9e1b59 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>    /* flush_sig_insns */
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index d8a67e60be8042ce6610c36283e42d9ff1d1bcbf..48b0f57b65f7e8f0820ba7f60d2df9e4823f2449 100644 (file)
@@ -31,6 +31,8 @@
 #include <asm/uctx.h>
 #include <asm/siginfo.h>
 #include <asm/visasm.h>
+#include <asm/switch_to.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 #include "systbls.h"
index 35c7897b009a9fd590cdb5ca8eb4ce41d488667f..0f6eebe71e6c91560585580a31621f0fb59a6f81 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index b19570d41a39eab11e7b60d2146aec678d0c8621..387834a9c56a5143a0a28b4e49018e43f4d95212 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index 12ff09824cd9f6b9f7a5f89ab1a5c9d9f88504d8..9f5e24ddcc70b0b10240f2a476b34610e011023b 100644 (file)
 #include <linux/init.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
 #include <asm/spitfire.h>
 #include <asm/oplib.h>
 #include <asm/hypervisor.h>
+#include <asm/cacheflush.h>
 
 struct poll {
        int fd;
index 1060e0672a4b439972fbfa0c728b6ba6403a777d..7d0c088e8abaa782bc34f1f03c3f6b4377d98544 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/oplib.h>
 #include <asm/timex.h>
 #include <asm/timer.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/idprom.h>
index 591f20ca9e4815726ec748b76a423fa7d95181e1..d2de21333146b4787bebf60438f31c58f57c8211 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/export.h>
 
 #include <asm/delay.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/oplib.h>
 #include <asm/page.h>
index 0cbdaa41cd1eb8fa19f4597b834da3c9a489b4ee..c72fdf55e1c108435b6f4193b1c8377b441eef3b 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/smp.h>
 #include <asm/delay.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/oplib.h>
 #include <asm/page.h>
@@ -41,6 +40,7 @@
 #include <asm/head.h>
 #include <asm/prom.h>
 #include <asm/memctrl.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 #include "kstack.h"
index 4d043a1b2492b062416eced20f64b8f11ee0b07d..c0ec897861934f3457f73237f533cfe65f630adf 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <linux/perf_event.h>
index 76e4ac1a13e1b9978be67102ed45ef5f0f19e274..dae85bc2eda5510b632650d62ad8d3be688669ca 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <linux/bitops.h>
@@ -24,6 +23,7 @@
 #include <linux/ratelimit.h>
 #include <linux/bitops.h>
 #include <asm/fpumacro.h>
+#include <asm/cacheflush.h>
 
 enum direction {
        load,    /* ld, ldd, ldh, ldsh */
index f67e28ef598cae92e660d93afb42a4241dc66dc4..5cffdc55f075a7c9229e40e6abfd97c44d211ed2 100644 (file)
@@ -119,13 +119,17 @@ static struct bus_type vio_bus_type = {
        .remove         = vio_device_remove,
 };
 
-int vio_register_driver(struct vio_driver *viodrv)
+int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
+                       const char *mod_name)
 {
        viodrv->driver.bus = &vio_bus_type;
+       viodrv->driver.name = viodrv->name;
+       viodrv->driver.owner = owner;
+       viodrv->driver.mod_name = mod_name;
 
        return driver_register(&viodrv->driver);
 }
-EXPORT_SYMBOL(vio_register_driver);
+EXPORT_SYMBOL(__vio_register_driver);
 
 void vio_unregister_driver(struct vio_driver *viodrv)
 {
index 73370674ccff49f797af2e8143e3ead2c34d233c..08e074b7eb6a025e985700e0bf2443ef30fcb1d2 100644 (file)
@@ -9,9 +9,9 @@
 
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
-#include <asm/system.h>
 #include <asm/fpumacro.h>
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 
 /* OPF field of various VIS instructions.  */
 
index e575bd2fe38167eadf61386b86df733807ef7ead..2bbe2f28ad23355edb2716828769061327c2f829 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 
 #include "sfp-util_64.h"
 #include <math-emu/soft-fp.h>
index 8a7f81743c126b1b8648584e20504dce6111dd48..09d6af22db2d76c0f3a660cd9783481fb8c43a47 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 
 #define BTFIXUP_OPTIMIZE_NOP
index 8023fd7e77b50c67e07a3830bc0e4b5e0571b746..7705c6731e2843697286e3d045279811d5691ed1 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/interrupt.h>
 #include <linux/kdebug.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/memreg.h>
index 7b00de61c5f1f73cf2e8c18c3cf07dfc1e190c50..c5f9021b1a01fb7c5c6c6c1ce61563190590273a 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/gfp.h>
 
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/vac-ops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index b3f5e7dfea51a21a4d2c28ee66518db1336a5023..21faaeea85dece95b991cbff707373345604289a 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/gfp.h>
 
 #include <asm/head.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 77d1b313e3441e9b616dffeed881b7cf5bfcc541..3e1ac8b96cae092017d57b5f6c1eb2023dc72af1 100644 (file)
@@ -36,8 +36,6 @@ extern unsigned long kern_locked_tte_data;
 
 extern void prom_world(int enter);
 
-extern void free_initmem(void);
-
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 #define VMEMMAP_CHUNK_SHIFT    22
 #define VMEMMAP_CHUNK          (1UL << VMEMMAP_CHUNK_SHIFT)
index 82ec8f666036bdcc45e6e3b92511a2833e57530c..c5bf2a6c38585f9495d0e106101fcfd110e9b27f 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
index 536412d8f4161d486a1d5b79cd00b605e3f1b323..c52add79b83dc9d53a3e605e8d92fd03816b9a1f 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/preempt.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
index a00f47b16c10a7ca15190e41f47c28489916ecc3..1cfb50f4cb9c9613b041ca047660b00743a6f2a8 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <linux/string.h>
 
 extern void restore_current(void);
index 9de6c8cfe04a555b26d347b05a414944076592e0..f95edcc54fd5cb33591798657daf7e716ba77211 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <linux/string.h>
 
 static int __prom_console_write_buf(const char *buf, int len)
index 677b6a10fbde3e2e4c6728027d67ae5b24ed9eeb..8dc0b6b271e89b18fbbca71ec2b004dd6d570699 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/auxio.h>
-#include <asm/system.h>
 
 extern void restore_current(void);
 
index e4f31d4d3715cc5c27752633ba58e052e853a956..f178b9dcc7b7c770e29f2b10fcf41e46c8c2477d 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/ldc.h>
 
 static int prom_service_exists(const char *service_name)
index d9850c2b9bf21275fb6e2de0ba69842a6c35b723..04a4540509dd87d5c533938810eaebeb55a21edf 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm/pstate.h>
 #include <asm/ldc.h>
index 0857aa9e839d2805e4cb26a25b554ee4d51b88f8..ad143c13bdc0cd5c473820474bd913f186678009 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/types.h>
-#include <asm/system.h>
 
 static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
 static int num_obio_ranges;
index 921dbeb8a70caddbdda187d48ef456583824a813..bb696da5d7cdbdbd4b20d98dedc9d12d53ced994 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
-#include <asm/system.h>
+#include <linux/types.h>
 
 #define ATOMIC_INIT(i) { (i) }
 
index c03349e0ca9f0866adcc17a20fb1321be9124af7..466dc4a39a4faf004d7d7dcabd683d6d41044f40 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _ASM_TILE_ATOMIC_32_H
 #define _ASM_TILE_ATOMIC_32_H
 
+#include <asm/barrier.h>
 #include <arch/chip.h>
 
 #ifndef __ASSEMBLY__
index 27fe667fddfeb82fd9ceec3638df571a3c5602ba..f4500c688ffad339f255ce122fee6d5b0c9bd241 100644 (file)
@@ -19,6 +19,7 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/barrier.h>
 #include <arch/spr_def.h>
 
 /* First, the 32-bit atomic ops that are "real" on our 64-bit platform. */
diff --git a/arch/tile/include/asm/barrier.h b/arch/tile/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..990a217
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _ASM_TILE_BARRIER_H
+#define _ASM_TILE_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <arch/chip.h>
+#include <arch/spr_def.h>
+#include <asm/timex.h>
+
+/*
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     b = 2;
+ *     memory_barrier();
+ *     p = &b;                         q = p;
+ *                                     read_barrier_depends();
+ *                                     d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     a = 2;
+ *     memory_barrier();
+ *     b = 3;                          y = b;
+ *                                     read_barrier_depends();
+ *                                     x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ */
+#define read_barrier_depends() do { } while (0)
+
+#define __sync()       __insn_mf()
+
+#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
+#include <hv/syscall_public.h>
+/*
+ * Issue an uncacheable load to each memory controller, then
+ * wait until those loads have completed.
+ */
+static inline void __mb_incoherent(void)
+{
+       long clobber_r10;
+       asm volatile("swint2"
+                    : "=R10" (clobber_r10)
+                    : "R10" (HV_SYS_fence_incoherent)
+                    : "r0", "r1", "r2", "r3", "r4",
+                      "r5", "r6", "r7", "r8", "r9",
+                      "r11", "r12", "r13", "r14",
+                      "r15", "r16", "r17", "r18", "r19",
+                      "r20", "r21", "r22", "r23", "r24",
+                      "r25", "r26", "r27", "r28", "r29");
+}
+#endif
+
+/* Fence to guarantee visibility of stores to incoherent memory. */
+static inline void
+mb_incoherent(void)
+{
+       __insn_mf();
+
+#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
+       {
+#if CHIP_HAS_TILE_WRITE_PENDING()
+               const unsigned long WRITE_TIMEOUT_CYCLES = 400;
+               unsigned long start = get_cycles_low();
+               do {
+                       if (__insn_mfspr(SPR_TILE_WRITE_PENDING) == 0)
+                               return;
+               } while ((get_cycles_low() - start) < WRITE_TIMEOUT_CYCLES);
+#endif /* CHIP_HAS_TILE_WRITE_PENDING() */
+               (void) __mb_incoherent();
+       }
+#endif /* CHIP_HAS_MF_WAITS_FOR_VICTIMS() */
+}
+
+#define fast_wmb()     __sync()
+#define fast_rmb()     __sync()
+#define fast_mb()      __sync()
+#define fast_iob()     mb_incoherent()
+
+#define wmb()          fast_wmb()
+#define rmb()          fast_rmb()
+#define mb()           fast_mb()
+#define iob()          fast_iob()
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#endif
+
+#define set_mb(var, value) \
+       do { var = value; mb(); } while (0)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_TILE_BARRIER_H */
index 571b118bfd9b29ca50246662cda4909ff703aee5..ddc4c1efde43e4524b3942a43d1fa94c2a247417 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/compiler.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 /* Tile-specific routines to support <asm/bitops.h>. */
 unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask);
index e9c8e381ee0ee8913cf08f60e05bb6fe051c63ea..58d021a9834f0b12d2b8bc2f091d32a22ca17baf 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/compiler.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 /* See <asm/bitops.h> for API comments. */
 
index e925f4bb498f40f93b1ffe6a04390f9732c2ffdb..0fc63c488edf28f923d82fafcbe9bc662b6884f0 100644 (file)
@@ -20,7 +20,6 @@
 /* Keep includes the same across arches.  */
 #include <linux/mm.h>
 #include <linux/cache.h>
-#include <asm/system.h>
 #include <arch/icache.h>
 
 /* Caches are physically-indexed and so don't need special treatment */
@@ -152,4 +151,14 @@ static inline void finv_buffer_local(void *buffer, size_t size)
  */
 void finv_buffer_remote(void *buffer, size_t size, int hfh);
 
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible:
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
 #endif /* _ASM_TILE_CACHEFLUSH_H */
index bf95f55b82b04e77c0e93ac8e28391c820ecaa08..4b4b28969a65266f0840f8e25774908054d70ca2 100644 (file)
@@ -242,17 +242,6 @@ long compat_sys_fallocate(int fd, int mode,
 long compat_sys_sched_rr_get_interval(compat_pid_t pid,
                                      struct compat_timespec __user *interval);
 
-/* Versions of compat functions that differ from generic Linux. */
-struct compat_msgbuf;
-long tile_compat_sys_msgsnd(int msqid,
-                           struct compat_msgbuf __user *msgp,
-                           size_t msgsz, int msgflg);
-long tile_compat_sys_msgrcv(int msqid,
-                           struct compat_msgbuf __user *msgp,
-                           size_t msgsz, long msgtyp, int msgflg);
-long tile_compat_sys_ptrace(compat_long_t request, compat_long_t pid,
-                           compat_long_t addr, compat_long_t data);
-
 /* Tilera Linux syscalls that don't have "compat" versions. */
 #define compat_sys_flush_cache sys_flush_cache
 
diff --git a/arch/tile/include/asm/exec.h b/arch/tile/include/asm/exec.h
new file mode 100644 (file)
index 0000000..a714e19
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _ASM_TILE_EXEC_H
+#define _ASM_TILE_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_TILE_EXEC_H */
index 1a20b7ef8ea229b43262901be4722024509c3752..67490910774d38af80cbd3ffc84e01bffd2abece 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/spinlock.h>
 #include <asm/processor.h>
 #include <asm/fixmap.h>
-#include <asm/system.h>
 
 struct mm_struct;
 struct vm_area_struct;
index 7caf0f36b0303ff99c2d8c3594bf8319e4c04d45..e58613e0752f65712dca236588747e0e893e426c 100644 (file)
@@ -31,6 +31,28 @@ void early_panic(const char *fmt, ...);
 void warn_early_printk(void);
 void __init disable_early_printk(void);
 
+/* Init-time routine to do tile-specific per-cpu setup. */
+void setup_cpu(int boot);
+
+/* User-level DMA management functions */
+void grant_dma_mpls(void);
+void restrict_dma_mpls(void);
+
+#ifdef CONFIG_HARDWALL
+/* User-level network management functions */
+void reset_network_state(void);
+void grant_network_mpls(void);
+void restrict_network_mpls(void);
+struct task_struct;
+int hardwall_deactivate(struct task_struct *task);
+
+/* Hook hardwall code into changes in affinity. */
+#define arch_set_cpus_allowed(p, new_mask) do { \
+       if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \
+               hardwall_deactivate(p); \
+} while (0)
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TILE_SETUP_H */
index 532124ae4b128f896335b0629af9043fc5277aaa..1aa759aeb5b3f0db2842a22c99b2f493dca10cf7 100644 (file)
@@ -43,10 +43,6 @@ void evaluate_message(int tag);
 /* Boot a secondary cpu */
 void online_secondary(void);
 
-/* Call a function on a specified set of CPUs (may include this one). */
-extern void on_each_cpu_mask(const struct cpumask *mask,
-                            void (*func)(void *), void *info, bool wait);
-
 /* Topology of the supervisor tile grid, and coordinates of boot processor */
 extern HV_Topology smp_topology;
 
@@ -91,9 +87,6 @@ void print_disabled_cpus(void);
 
 #else /* !CONFIG_SMP */
 
-#define on_each_cpu_mask(mask, func, info, wait)               \
-  do { if (cpumask_test_cpu(0, (mask))) func(info); } while (0)
-
 #define smp_master_cpu         0
 #define smp_height             1
 #define smp_width              1
index a5e4208d34f9ad9e6be2982a16046fbd04b8d34e..c0a77b38d39a73c8b7064b4b92a340a92b7f83e8 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/atomic.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <linux/compiler.h>
 
 /*
diff --git a/arch/tile/include/asm/switch_to.h b/arch/tile/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..1d48c5f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _ASM_TILE_SWITCH_TO_H
+#define _ASM_TILE_SWITCH_TO_H
+
+#include <arch/sim_def.h>
+
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ * The number of callee-saved registers saved on the kernel stack
+ * is defined here for use in copy_thread() and must agree with __switch_to().
+ */
+#define CALLEE_SAVED_FIRST_REG 30
+#define CALLEE_SAVED_REGS_COUNT 24   /* r30 to r52, plus an empty to align */
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/*
+ * Pause the DMA engine and static network before task switching.
+ */
+#define prepare_arch_switch(next) _prepare_arch_switch(next)
+void _prepare_arch_switch(struct task_struct *next);
+
+struct task_struct;
+#define switch_to(prev, next, last) ((last) = _switch_to((prev), (next)))
+extern struct task_struct *_switch_to(struct task_struct *prev,
+                                     struct task_struct *next);
+
+/* Helper function for _switch_to(). */
+extern struct task_struct *__switch_to(struct task_struct *prev,
+                                      struct task_struct *next,
+                                      unsigned long new_system_save_k_0);
+
+/* Address that switched-away from tasks are at. */
+extern unsigned long get_switch_to_pc(void);
+
+/*
+ * Kernel threads can check to see if they need to migrate their
+ * stack whenever they return from a context switch; for user
+ * threads, we defer until they are returning to user-space.
+ */
+#define finish_arch_switch(prev) do {                                     \
+       if (unlikely((prev)->state == TASK_DEAD))                         \
+               __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT |       \
+                       ((prev)->pid << _SIM_CONTROL_OPERATOR_BITS));     \
+       __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH |             \
+               (current->pid << _SIM_CONTROL_OPERATOR_BITS));            \
+       if (current->mm == NULL && !kstack_hash &&                        \
+           current_thread_info()->homecache_cpu != smp_processor_id())   \
+               homecache_migrate_kthread();                              \
+} while (0)
+
+/* Support function for forking a new task. */
+void ret_from_fork(void);
+
+/* Called from ret_from_fork() when a new process starts up. */
+struct task_struct *sim_notify_fork(struct task_struct *prev);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_TILE_SWITCH_TO_H */
diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h
deleted file mode 100644 (file)
index 23d1842..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-#ifndef _ASM_TILE_SYSTEM_H
-#define _ASM_TILE_SYSTEM_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-/* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */
-#include <asm/ptrace.h>
-
-#include <arch/chip.h>
-#include <arch/sim_def.h>
-#include <arch/spr_def.h>
-
-/*
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     b = 2;
- *     memory_barrier();
- *     p = &b;                         q = p;
- *                                     read_barrier_depends();
- *                                     d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     a = 2;
- *     memory_barrier();
- *     b = 3;                          y = b;
- *                                     read_barrier_depends();
- *                                     x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- */
-
-#define read_barrier_depends() do { } while (0)
-
-#define __sync()       __insn_mf()
-
-#if CHIP_HAS_SPLIT_CYCLE()
-#define get_cycles_low() __insn_mfspr(SPR_CYCLE_LOW)
-#else
-#define get_cycles_low() __insn_mfspr(SPR_CYCLE)   /* just get all 64 bits */
-#endif
-
-#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-#include <hv/syscall_public.h>
-/*
- * Issue an uncacheable load to each memory controller, then
- * wait until those loads have completed.
- */
-static inline void __mb_incoherent(void)
-{
-       long clobber_r10;
-       asm volatile("swint2"
-                    : "=R10" (clobber_r10)
-                    : "R10" (HV_SYS_fence_incoherent)
-                    : "r0", "r1", "r2", "r3", "r4",
-                      "r5", "r6", "r7", "r8", "r9",
-                      "r11", "r12", "r13", "r14",
-                      "r15", "r16", "r17", "r18", "r19",
-                      "r20", "r21", "r22", "r23", "r24",
-                      "r25", "r26", "r27", "r28", "r29");
-}
-#endif
-
-/* Fence to guarantee visibility of stores to incoherent memory. */
-static inline void
-mb_incoherent(void)
-{
-       __insn_mf();
-
-#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-       {
-#if CHIP_HAS_TILE_WRITE_PENDING()
-               const unsigned long WRITE_TIMEOUT_CYCLES = 400;
-               unsigned long start = get_cycles_low();
-               do {
-                       if (__insn_mfspr(SPR_TILE_WRITE_PENDING) == 0)
-                               return;
-               } while ((get_cycles_low() - start) < WRITE_TIMEOUT_CYCLES);
-#endif /* CHIP_HAS_TILE_WRITE_PENDING() */
-               (void) __mb_incoherent();
-       }
-#endif /* CHIP_HAS_MF_WAITS_FOR_VICTIMS() */
-}
-
-#define fast_wmb()     __sync()
-#define fast_rmb()     __sync()
-#define fast_mb()      __sync()
-#define fast_iob()     mb_incoherent()
-
-#define wmb()          fast_wmb()
-#define rmb()          fast_rmb()
-#define mb()           fast_mb()
-#define iob()          fast_iob()
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#endif
-
-#define set_mb(var, value) \
-       do { var = value; mb(); } while (0)
-
-/*
- * Pause the DMA engine and static network before task switching.
- */
-#define prepare_arch_switch(next) _prepare_arch_switch(next)
-void _prepare_arch_switch(struct task_struct *next);
-
-
-/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- * The number of callee-saved registers saved on the kernel stack
- * is defined here for use in copy_thread() and must agree with __switch_to().
- */
-#endif /* !__ASSEMBLY__ */
-#define CALLEE_SAVED_FIRST_REG 30
-#define CALLEE_SAVED_REGS_COUNT 24   /* r30 to r52, plus an empty to align */
-#ifndef __ASSEMBLY__
-struct task_struct;
-#define switch_to(prev, next, last) ((last) = _switch_to((prev), (next)))
-extern struct task_struct *_switch_to(struct task_struct *prev,
-                                     struct task_struct *next);
-
-/* Helper function for _switch_to(). */
-extern struct task_struct *__switch_to(struct task_struct *prev,
-                                      struct task_struct *next,
-                                      unsigned long new_system_save_k_0);
-
-/* Address that switched-away from tasks are at. */
-extern unsigned long get_switch_to_pc(void);
-
-/*
- * On SMP systems, when the scheduler does migration-cost autodetection,
- * it needs a way to flush as much of the CPU's caches as possible:
- *
- * TODO: fill this in!
- */
-static inline void sched_cacheflush(void)
-{
-}
-
-#define arch_align_stack(x) (x)
-
-/*
- * Is the kernel doing fixups of unaligned accesses?  If <0, no kernel
- * intervention occurs and SIGBUS is delivered with no data address
- * info.  If 0, the kernel single-steps the instruction to discover
- * the data address to provide with the SIGBUS.  If 1, the kernel does
- * a fixup.
- */
-extern int unaligned_fixup;
-
-/* Is the kernel printing on each unaligned fixup? */
-extern int unaligned_printk;
-
-/* Number of unaligned fixups performed */
-extern unsigned int unaligned_fixup_count;
-
-/* Init-time routine to do tile-specific per-cpu setup. */
-void setup_cpu(int boot);
-
-/* User-level DMA management functions */
-void grant_dma_mpls(void);
-void restrict_dma_mpls(void);
-
-#ifdef CONFIG_HARDWALL
-/* User-level network management functions */
-void reset_network_state(void);
-void grant_network_mpls(void);
-void restrict_network_mpls(void);
-int hardwall_deactivate(struct task_struct *task);
-
-/* Hook hardwall code into changes in affinity. */
-#define arch_set_cpus_allowed(p, new_mask) do { \
-       if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \
-               hardwall_deactivate(p); \
-} while (0)
-#endif
-
-/*
- * Kernel threads can check to see if they need to migrate their
- * stack whenever they return from a context switch; for user
- * threads, we defer until they are returning to user-space.
- */
-#define finish_arch_switch(prev) do {                                     \
-       if (unlikely((prev)->state == TASK_DEAD))                         \
-               __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT |       \
-                       ((prev)->pid << _SIM_CONTROL_OPERATOR_BITS));     \
-       __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH |             \
-               (current->pid << _SIM_CONTROL_OPERATOR_BITS));            \
-       if (current->mm == NULL && !kstack_hash &&                        \
-           current_thread_info()->homecache_cpu != smp_processor_id())   \
-               homecache_migrate_kthread();                              \
-} while (0)
-
-/* Support function for forking a new task. */
-void ret_from_fork(void);
-
-/* Called from ret_from_fork() when a new process starts up. */
-struct task_struct *sim_notify_fork(struct task_struct *prev);
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_TILE_SYSTEM_H */
index 29921f0b86da76f2e7c15845179de0f194245225..dc987d53e2a92fffce3eda254ad42b169233f564 100644 (file)
@@ -29,11 +29,13 @@ typedef unsigned long long cycles_t;
 
 #if CHIP_HAS_SPLIT_CYCLE()
 cycles_t get_cycles(void);
+#define get_cycles_low() __insn_mfspr(SPR_CYCLE_LOW)
 #else
 static inline cycles_t get_cycles(void)
 {
        return __insn_mfspr(SPR_CYCLE);
 }
+#define get_cycles_low() __insn_mfspr(SPR_CYCLE)   /* just get all 64 bits */
 #endif
 
 cycles_t get_clock_rate(void);
index 137e2de5b102b08920ff674ad1aa6af55084c06a..37dfbe5988722d4810c20693400bec5480b7d6c6 100644 (file)
 #define get_unaligned  __get_unaligned_le
 #define put_unaligned  __put_unaligned_le
 
+/*
+ * Is the kernel doing fixups of unaligned accesses?  If <0, no kernel
+ * intervention occurs and SIGBUS is delivered with no data address
+ * info.  If 0, the kernel single-steps the instruction to discover
+ * the data address to provide with the SIGBUS.  If 1, the kernel does
+ * a fixup.
+ */
+extern int unaligned_fixup;
+
+/* Is the kernel printing on each unaligned fixup? */
+extern int unaligned_printk;
+
+/* Number of unaligned fixups performed */
+extern unsigned int unaligned_fixup_count;
+
 #endif /* _ASM_TILE_UNALIGNED_H */
index bf5e9d70266c72fe9ef45e30cdade23ef0f2e374..d67459b9ac2aa43f4c44eb50125c0143509e873f 100644 (file)
@@ -16,7 +16,6 @@
 #define __SYSCALL_COMPAT
 
 #include <linux/compat.h>
-#include <linux/msg.h>
 #include <linux/syscalls.h>
 #include <linux/kdev_t.h>
 #include <linux/fs.h>
@@ -95,52 +94,10 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid,
        return ret;
 }
 
-/*
- * The usual compat_sys_msgsnd() and _msgrcv() seem to be assuming
- * some different calling convention than our normal 32-bit tile code.
- */
-
-/* Already defined in ipc/compat.c, but we need it here. */
-struct compat_msgbuf {
-       compat_long_t mtype;
-       char mtext[1];
-};
-
-long tile_compat_sys_msgsnd(int msqid,
-                           struct compat_msgbuf __user *msgp,
-                           size_t msgsz, int msgflg)
-{
-       compat_long_t mtype;
-
-       if (get_user(mtype, &msgp->mtype))
-               return -EFAULT;
-       return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
-}
-
-long tile_compat_sys_msgrcv(int msqid,
-                           struct compat_msgbuf __user *msgp,
-                           size_t msgsz, long msgtyp, int msgflg)
-{
-       long err, mtype;
-
-       err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
-       if (err < 0)
-               goto out;
-
-       if (put_user(mtype, &msgp->mtype))
-               err = -EFAULT;
- out:
-       return err;
-}
-
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
 
-/* The generic versions of these don't work for Tile. */
-#define compat_sys_msgrcv tile_compat_sys_msgrcv
-#define compat_sys_msgsnd tile_compat_sys_msgsnd
-
 /* See comments in sys.c */
 #define compat_sys_fadvise64_64 sys32_fadvise64_64
 #define compat_sys_readahead sys32_readahead
index 493a0e66d916c618f867034db5647f72acd61999..afb9c9a0d8872be3c2bf12a797a45035ca0ee463 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/irqflags.h>
 #include <asm/setup.h>
 #include <hv/hypervisor.h>
 
index 62d820833c68bc2ee34185f3ad3f4f6c080bff15..7a93270464045753c76caa4032716ea6981c082c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sysctl.h>
 #include <linux/hardirq.h>
 #include <linux/mman.h>
+#include <asm/unaligned.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
index 6ae495ef2b99db3b5f006bfe5d6011dd0a0c8cc6..30caecac94dcae955928900c4d6841c154263810 100644 (file)
 #include <linux/kernel.h>
 #include <linux/tracehook.h>
 #include <linux/signal.h>
-#include <asm/system.h>
 #include <asm/stack.h>
 #include <asm/homecache.h>
 #include <asm/syscalls.h>
 #include <asm/traps.h>
+#include <asm/setup.h>
 #ifdef CONFIG_HARDWALL
 #include <asm/hardwall.h>
 #endif
 #include <arch/chip.h>
 #include <arch/abi.h>
+#include <arch/sim_def.h>
 
 
 /*
index caa13101c26474f352c4e60a00666d1ccefcb6de..c12280c2d9048a5c28ae4608a60391f853bdee1d 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <arch/spr_def.h>
 #include <asm/processor.h>
+#include <asm/switch_to.h>
 
 /*
  * See <asm/system.h>; called with prev and next task_struct pointers.
index f748c1e852857224066df0a460a75cb945c2d264..0829fd01fa30be16324309ea7e52b421724ff75e 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <arch/spr_def.h>
 #include <asm/processor.h>
+#include <asm/switch_to.h>
 
 /*
  * See <asm/system.h>; called with prev and next task_struct pointers.
index b7a8795040863bc76727d61bd48debd15bdc0f63..bc1eb586e24db24bf924644fe5e68b3424e7a308 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <asm/cacheflush.h>
+#include <asm/unaligned.h>
 #include <arch/abi.h>
 #include <arch/opcode.h>
 
index c52224d5ed45f06a38f4461e19f485a2bb4cadb3..a44e103c5a636670bdbd358f5143419c24d19d7a 100644 (file)
@@ -87,25 +87,6 @@ void send_IPI_allbutself(int tag)
        send_IPI_many(&mask, tag);
 }
 
-
-/*
- * Provide smp_call_function_mask, but also run function locally
- * if specified in the mask.
- */
-void on_each_cpu_mask(const struct cpumask *mask, void (*func)(void *),
-                     void *info, bool wait)
-{
-       int cpu = get_cpu();
-       smp_call_function_many(mask, func, info, wait);
-       if (cpumask_test_cpu(cpu, mask)) {
-               local_irq_disable();
-               func(info);
-               local_irq_enable();
-       }
-       put_cpu();
-}
-
-
 /*
  * Functions related to starting/stopping cpus.
  */
index 4f47b8a356df68241ae61e459084fb3d5a3ea945..2bb6602a1ee711c64146319a39c657de79f5a7b5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/ptrace.h>
 #include <asm/stack.h>
 #include <asm/traps.h>
+#include <asm/setup.h>
 
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
index 1a00fb64fc88316df271121ae6ced4bc96817e2e..758b6038c2b78eabe41627ba5b018e289a0d677e 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
+#include <arch/sim_def.h>
 
 /* Notify a running simulator, if any, that an exec just occurred. */
 static void sim_notify_exec(const char *binary_name)
index c1eaaa1fcc2089bed7d135875d9fe654d3254e0a..cba30e9547b41682c8cfca0f3577637f1ff8cbbf 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
 #include <asm/traps.h>
index 7309988c9794c82f195572afd2b63658a4431cb4..830c4908ea76cf4c7156777db8a8cced9fb887f9 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
index de7d8e21e01d8980009de9840ccbd2c30690b2f1..87303693a0727faa96d844d58dc9115a4dd85b10 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
index 69c0252345f10e0ad3061df4d45c325475776c18..21a423bae5e853fa02673ab82391d4c7dd88cc19 100644 (file)
@@ -2,7 +2,6 @@
 #define __UM_FIXMAP_H
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/kmap_types.h>
 #include <asm/archparam.h>
 #include <asm/page.h>
index ca113d6999c5279df35ad1d47a275ace8fd18463..34b789b711151edf6d86e02c8122bd2f40d0896a 100644 (file)
@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
 generic-y += atomic.h
 generic-y += auxvec.h
 generic-y += bitsperlong.h
-generic-y += bug.h
 generic-y += bugs.h
 generic-y += cputime.h
 generic-y += current.h
diff --git a/arch/unicore32/include/asm/barrier.h b/arch/unicore32/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..a6620e5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Memory barrier implementations for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_BARRIER_H__
+#define __UNICORE_BARRIER_H__
+
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("" : : : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+
+#define mb()                           barrier()
+#define rmb()                          barrier()
+#define wmb()                          barrier()
+#define smp_mb()                       barrier()
+#define smp_rmb()                      barrier()
+#define smp_wmb()                      barrier()
+#define read_barrier_depends()         do { } while (0)
+#define smp_read_barrier_depends()     do { } while (0)
+
+#define set_mb(var, value)             do { var = value; smp_mb(); } while (0)
+
+#endif /* __UNICORE_BARRIER_H__ */
diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h
new file mode 100644 (file)
index 0000000..b1ff8ca
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Bug handling for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_BUG_H__
+#define __UNICORE_BUG_H__
+
+#include <asm-generic/bug.h>
+
+struct pt_regs;
+struct siginfo;
+
+extern void die(const char *msg, struct pt_regs *regs, int err);
+extern void uc32_notify_die(const char *str, struct pt_regs *regs,
+               struct siginfo *info, unsigned long err, unsigned long trap);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
+#endif /* __UNICORE_BUG_H__ */
diff --git a/arch/unicore32/include/asm/cmpxchg.h b/arch/unicore32/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..df4d5ac
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Atomics xchg/cmpxchg for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_CMPXCHG_H__
+#define __UNICORE_CMPXCHG_H__
+
+/*
+ * Generate a link failure on undefined symbol if the pointer points to a value
+ * of unsupported size.
+ */
+extern void __xchg_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+               int size)
+{
+       unsigned long ret;
+
+       switch (size) {
+       case 1:
+               asm volatile("swapb     %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       case 4:
+               asm volatile("swapw     %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       default:
+               ret = __xchg_bad_pointer();
+       }
+
+       return ret;
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+               ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),     \
+               (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)                                     \
+               __cmpxchg64_local_generic((ptr), (o), (n))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif /* __UNICORE_CMPXCHG_H__ */
diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h
new file mode 100644 (file)
index 0000000..06d1f0f
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Process execution bits for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_EXEC_H__
+#define __UNICORE_EXEC_H__
+
+#define arch_align_stack(x)            (x)
+
+#endif /* __UNICORE_EXEC_H__ */
diff --git a/arch/unicore32/include/asm/hwdef-copro.h b/arch/unicore32/include/asm/hwdef-copro.h
new file mode 100644 (file)
index 0000000..a3292f0
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Co-processor register definitions for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_HWDEF_COPRO_H__
+#define __UNICORE_HWDEF_COPRO_H__
+
+/*
+ * Control Register bits (CP#0 CR1)
+ */
+#define CR_M   (1 << 0)        /* MMU enable                           */
+#define CR_A   (1 << 1)        /* Alignment abort enable               */
+#define CR_D   (1 << 2)        /* Dcache enable                        */
+#define CR_I   (1 << 3)        /* Icache enable                        */
+#define CR_B   (1 << 4)        /* Dcache write mechanism: write back   */
+#define CR_T   (1 << 5)        /* Burst enable                         */
+#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
+
+#ifndef __ASSEMBLY__
+
+#define vectors_high()         (cr_alignment & CR_V)
+
+extern unsigned long cr_no_alignment;  /* defined in entry.S */
+extern unsigned long cr_alignment;     /* defined in entry.S */
+
+static inline unsigned int get_cr(void)
+{
+       unsigned int val;
+       asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
+       return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+       asm volatile("movc p0.c1, %0, #0" : : "r" (val) : "cc");
+       isb();
+}
+
+extern void adjust_cr(unsigned long mask, unsigned long set);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __UNICORE_HWDEF_COPRO_H__ */
index adddf6d640771ac88ab0c5b016ad96769cca6a9e..39decb6e6f576db647e1a78a43cce3b5683d47b9 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/memory.h>
-#include <asm/system.h>
 
 #define PCI_IOBASE     PKUNITY_PCILIO_BASE
 #include <asm-generic/io.h>
diff --git a/arch/unicore32/include/asm/switch_to.h b/arch/unicore32/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..39572d2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Task switching for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * 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.
+ */
+#ifndef __UNICORE_SWITCH_TO_H__
+#define __UNICORE_SWITCH_TO_H__
+
+struct task_struct;
+struct thread_info;
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.  schedule() itself
+ * contains the memory barrier to tell GCC not to cache `current'.
+ */
+extern struct task_struct *__switch_to(struct task_struct *,
+               struct thread_info *, struct thread_info *);
+
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               last = __switch_to(prev, task_thread_info(prev),        \
+                                       task_thread_info(next));        \
+       } while (0)
+
+#endif /* __UNICORE_SWITCH_TO_H__ */
diff --git a/arch/unicore32/include/asm/system.h b/arch/unicore32/include/asm/system.h
deleted file mode 100644 (file)
index 246b71c..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/system.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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.
- */
-#ifndef __UNICORE_SYSTEM_H__
-#define __UNICORE_SYSTEM_H__
-
-#ifdef __KERNEL__
-
-/*
- * CR1 bits (CP#0 CR1)
- */
-#define CR_M   (1 << 0)        /* MMU enable                           */
-#define CR_A   (1 << 1)        /* Alignment abort enable               */
-#define CR_D   (1 << 2)        /* Dcache enable                        */
-#define CR_I   (1 << 3)        /* Icache enable                        */
-#define CR_B   (1 << 4)        /* Dcache write mechanism: write back   */
-#define CR_T   (1 << 5)        /* Burst enable                         */
-#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-struct thread_info;
-struct task_struct;
-
-struct pt_regs;
-
-void die(const char *msg, struct pt_regs *regs, int err);
-
-struct siginfo;
-void uc32_notify_die(const char *str, struct pt_regs *regs,
-               struct siginfo *info, unsigned long err, unsigned long trap);
-
-void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
-                                      struct pt_regs *),
-                    int sig, int code, const char *name);
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-struct mm_struct;
-extern void show_pte(struct mm_struct *mm, unsigned long addr);
-extern void __show_regs(struct pt_regs *);
-
-extern int cpu_architecture(void);
-extern void cpu_init(void);
-
-#define vectors_high() (cr_alignment & CR_V)
-
-#define isb() __asm__ __volatile__ ("" : : : "memory")
-#define dsb() __asm__ __volatile__ ("" : : : "memory")
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define read_barrier_depends()         do { } while (0)
-#define smp_read_barrier_depends()     do { } while (0)
-
-#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
-extern unsigned long cr_no_alignment;  /* defined in entry-unicore.S */
-extern unsigned long cr_alignment;     /* defined in entry-unicore.S */
-
-static inline unsigned int get_cr(void)
-{
-       unsigned int val;
-       asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_cr(unsigned int val)
-{
-       asm volatile("movc p0.c1, %0, #0        @set CR"
-         : : "r" (val) : "cc");
-       isb();
-}
-
-extern void adjust_cr(unsigned long mask, unsigned long set);
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.  schedule() itself
- * contains the memory barrier to tell GCC not to cache `current'.
- */
-extern struct task_struct *__switch_to(struct task_struct *,
-               struct thread_info *, struct thread_info *);
-extern void panic(const char *fmt, ...);
-
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       last = __switch_to(prev,                                        \
-               task_thread_info(prev), task_thread_info(next));        \
-} while (0)
-
-static inline unsigned long
-__xchg(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long ret;
-
-       switch (size) {
-       case 1:
-               asm volatile("@ __xchg1\n"
-               "       swapb   %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       case 4:
-               asm volatile("@ __xchg4\n"
-               "       swapw   %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       default:
-               panic("xchg: bad data size: ptr 0x%p, size %d\n",
-                       ptr, size);
-       }
-
-       return ret;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-               ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),     \
-               (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n)                                     \
-               __cmpxchg64_local_generic((ptr), (o), (n))
-
-#include <asm-generic/cmpxchg.h>
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif
index 2acda503a6d95fdf3116359c4b9cb0d61adab296..897e11ad8124a0eb977dcbf54eec37254fbb6958 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/errno.h>
 
 #include <asm/memory.h>
-#include <asm/system.h>
 
 #define __copy_from_user       __copy_from_user
 #define __copy_to_user         __copy_to_user
index ae441bc3122c60799a91c780fe1bdcc18b0c6e02..ed2d4d78d9c434282bbc05f4e10837bb11c37a0a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/errno.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
index 8caf322e110d79eba0f90c916dae72d6f6113fa8..e8f0b98c02eed5d9d9cfe29e4ccaf68cc54f752d 100644 (file)
@@ -17,7 +17,7 @@
 #include <generated/asm-offsets.h>
 #include <asm/memory.h>
 #include <asm/thread_info.h>
-#include <asm/system.h>
+#include <asm/hwdef-copro.h>
 #include <asm/pgtable-hwdef.h>
 
 #if (PHYS_OFFSET & 0x003fffff)
index 7d0f0b7983a0e2c7d5fc5d312ba9680fdd03b659..d75ef8b6cb5618f28cb2ed0db4192910fcf056e2 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/suspend.h>
 #include <linux/bootmem.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index d4efa7d679ffe5e9d10d1ac09cfcfb83c52dcddb..0be5ccd7ccd223c17b7979ba192abade30e17c1c 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/syscore_ops.h>
 #include <linux/gpio.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 
 #include "setup.h"
index d98bd812cae1ea17efcb314a1cccee9639636b37..d285d71cbe356483d44893ae8e6d1a3251e8508e 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/io.h>
 
 #include <asm/checksum.h>
-#include <asm/system.h>
 
 #include "ksyms.h"
 
index 432b4291f37b63a8ccab05b81c52a409ecdef9e7..b6f0458c3143187ced10fdde2eb4286548c869b8 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/stacktrace.h>
 
 #include "setup.h"
index dcd1306eb5c6ddae6e17caf492f5e8d5c443b25c..f23955028a183f70c0e0982ff934a06157bad659 100644 (file)
 #ifndef __UNICORE_KERNEL_SETUP_H__
 #define __UNICORE_KERNEL_SETUP_H__
 
+#include <asm/hwdef-copro.h>
+
 extern void paging_init(void);
 extern void puv3_core_init(void);
+extern void cpu_init(void);
 
 extern void puv3_ps2_init(void);
 extern void pci_puv3_preinit(void);
index b9a26465e72822674a507e5583b4aa6f25914e2a..2054f0d4db1355fcb6b7891a7a2023b6218ef756 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/unistd.h>
 
 #include <asm/cacheflush.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include "setup.h"
index 28f576d733ee1c5f87424fa20fbf793636994e55..de7dc5fdd58b7454c9319265bd621ae67f8715af 100644 (file)
@@ -24,6 +24,8 @@
 #include <asm/tlbflush.h>
 #include <asm/unaligned.h>
 
+#include "mm.h"
+
 #define CODING_BITS(i) (i & 0xe0000120)
 
 #define LDST_P_BIT(i)  (i & (1 << 28)) /* Preindex             */
index 283aa4b50b7a3354714973b1a79623b3660e7b5b..2eeb9c04cab057b5a2c6f542e251d6762cd6621b 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/sched.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
index 93478cc8b26dc430beba5b3a60387a5ad60f87c5..6d4c096ffa2a8bb59aaf7d1635cc70d7276b0361 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/pagemap.h>
 
 #include <asm/cacheflush.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 
 void flush_cache_mm(struct mm_struct *mm)
index 3296bca0f1f7a1f75597089e9340c700900006c8..05c7f532eee2104d9f8c564661735e9053fa6258 100644 (file)
@@ -9,6 +9,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/hwdef-copro.h>
+
 /* the upper-most page table pointer */
 extern pmd_t *top_pmd;
 extern int sysctl_overcommit_memory;
@@ -34,6 +36,9 @@ struct mem_type {
 const struct mem_type *get_mem_type(unsigned int type);
 
 extern void __flush_dcache_page(struct address_space *, struct page *);
+extern void hook_fault_code(int nr, int (*fn)
+               (unsigned long, unsigned int, struct pt_regs *),
+               int sig, int code, const char *name);
 
 void __init bootmem_init(void);
 void uc32_mm_memblock_reserve(void);
index 90195235596943ff7fbb3b87a695eca988c5c9b8..1d14cc6b79ad399d1ad293030c9f2271d9e5df1d 100644 (file)
@@ -69,7 +69,6 @@ config X86
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_TEXT_POKE_SMP
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
        select SPARSE_IRQ
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IRQ_PROBE
@@ -2125,6 +2124,13 @@ config NET5501
        ---help---
          This option enables system support for the Soekris Engineering net5501.
 
+config GEOS
+       bool "Traverse Technologies GEOS System Support (LEDS, GPIO, etc)"
+       select GPIOLIB
+       depends on DMI
+       ---help---
+         This option enables system support for the Traverse Technologies GEOS.
+
 endif # X86_32
 
 config AMD_NB
@@ -2157,9 +2163,9 @@ config IA32_EMULATION
        depends on X86_64
        select COMPAT_BINFMT_ELF
        ---help---
-         Include code to run 32-bit programs under a 64-bit kernel. You should
-         likely turn this on, unless you're 100% sure that you don't have any
-         32-bit programs left.
+         Include code to run legacy 32-bit programs under a
+         64-bit kernel. You should likely turn this on, unless you're
+         100% sure that you don't have any 32-bit programs left.
 
 config IA32_AOUT
        tristate "IA32 a.out support"
@@ -2167,9 +2173,23 @@ config IA32_AOUT
        ---help---
          Support old a.out binaries in the 32bit emulation.
 
+config X86_X32
+       bool "x32 ABI for 64-bit mode (EXPERIMENTAL)"
+       depends on X86_64 && IA32_EMULATION && EXPERIMENTAL
+       ---help---
+         Include code to run binaries for the x32 native 32-bit ABI
+         for 64-bit processors.  An x32 process gets access to the
+         full 64-bit register file and wide data path while leaving
+         pointers at 32 bits for smaller memory footprint.
+
+         You will need a recent binutils (2.22 or later) with
+         elf32_x86_64 support enabled to compile a kernel with this
+         option set.
+
 config COMPAT
        def_bool y
-       depends on IA32_EMULATION
+       depends on IA32_EMULATION || X86_X32
+       select ARCH_WANT_OLD_COMPAT_IPC
 
 config COMPAT_FOR_U64_ALIGNMENT
        def_bool COMPAT
index 209ba1294592c406bd735df889f43f6272acbddb..968dbe24a255453bb3bb3768cd76f2f72b424bcc 100644 (file)
@@ -82,6 +82,22 @@ ifdef CONFIG_CC_STACKPROTECTOR
         endif
 endif
 
+ifdef CONFIG_X86_X32
+       x32_ld_ok := $(call try-run,\
+                       /bin/echo -e '1: .quad 1b' | \
+                       $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" - && \
+                       $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMPO" && \
+                       $(LD) -m elf32_x86_64 "$$TMPO" -o "$$TMP",y,n)
+        ifeq ($(x32_ld_ok),y)
+                CONFIG_X86_X32_ABI := y
+                KBUILD_AFLAGS += -DCONFIG_X86_X32_ABI
+                KBUILD_CFLAGS += -DCONFIG_X86_X32_ABI
+        else
+                $(warning CONFIG_X86_X32 enabled but no binutils support)
+        endif
+endif
+export CONFIG_X86_X32_ABI
+
 # Don't unroll struct assignments with kmemcheck enabled
 ifeq ($(CONFIG_KMEMCHECK),y)
        KBUILD_CFLAGS += $(call cc-option,-fno-builtin-memcpy)
index 2bf18059fbea710667d4636477b41a21a1fb1571..119db67dcb03402a06ad889faa8bf73d82876e91 100644 (file)
@@ -15,23 +15,28 @@ CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
-CONFIG_USER_NS=y
-CONFIG_PID_NS=y
-CONFIG_NET_NS=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SGI_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_X86_GENERIC=y
 CONFIG_HPET_TIMER=y
 CONFIG_SCHED_SMT=y
@@ -51,14 +56,12 @@ CONFIG_HZ_1000=y
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
 # CONFIG_COMPAT_VDSO is not set
-CONFIG_PM=y
+CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
 CONFIG_PM_TRACE_RTC=y
-CONFIG_HIBERNATION=y
 CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_DOCK=y
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_DEBUG=y
 # CONFIG_CPU_FREQ_STAT is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
@@ -69,7 +72,6 @@ CONFIG_PCI_MSI=y
 CONFIG_PCCARD=y
 CONFIG_YENTA=y
 CONFIG_HOTPLUG_PCI=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_BINFMT_MISC=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -120,7 +122,6 @@ CONFIG_NF_CONNTRACK_IPV4=y
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_LOG=y
 CONFIG_IP_NF_TARGET_ULOG=y
 CONFIG_NF_NAT=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
@@ -128,7 +129,6 @@ CONFIG_IP_NF_MANGLE=y
 CONFIG_NF_CONNTRACK_IPV6=y
 CONFIG_IP6_NF_IPTABLES=y
 CONFIG_IP6_NF_MATCH_IPV6HEADER=y
-CONFIG_IP6_NF_TARGET_LOG=y
 CONFIG_IP6_NF_FILTER=y
 CONFIG_IP6_NF_TARGET_REJECT=y
 CONFIG_IP6_NF_MANGLE=y
@@ -169,25 +169,20 @@ CONFIG_DM_ZERO=y
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_VENDOR_3COM=y
+CONFIG_NETCONSOLE=y
+CONFIG_BNX2=y
+CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
-CONFIG_NET_PCI=y
-CONFIG_FORCEDETH=y
 CONFIG_E100=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_SKY2=y
 CONFIG_NE2K_PCI=y
+CONFIG_FORCEDETH=y
 CONFIG_8139TOO=y
 # CONFIG_8139TOO_PIO is not set
-CONFIG_E1000=y
-CONFIG_E1000E=y
 CONFIG_R8169=y
-CONFIG_SKY2=y
-CONFIG_TIGON3=y
-CONFIG_BNX2=y
-CONFIG_TR=y
-CONFIG_NET_PCMCIA=y
 CONFIG_FDDI=y
-CONFIG_NETCONSOLE=y
 CONFIG_INPUT_POLLDEV=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -196,6 +191,7 @@ CONFIG_INPUT_TABLET=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -205,7 +201,6 @@ CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
-# CONFIG_LEGACY_PTYS is not set
 CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 CONFIG_HPET=y
@@ -220,7 +215,6 @@ CONFIG_DRM_I915=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_EFI=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
@@ -283,7 +277,6 @@ CONFIG_ZISOFS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=y
@@ -291,18 +284,6 @@ CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-CONFIG_MAC_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_SGI_PARTITION=y
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -317,13 +298,12 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUG_RODATA_TEST is not set
 CONFIG_DEBUG_NX_TEST=m
 CONFIG_DEBUG_BOOT_PARAMS=y
index 058a35b8286c9e60b664e53986c1fe64a94ed840..76eb2903809f6104b13861129ccb9525d6067a57 100644 (file)
@@ -1,4 +1,3 @@
-CONFIG_64BIT=y
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
@@ -16,26 +15,29 @@ CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
-CONFIG_UTS_NS=y
-CONFIG_IPC_NS=y
-CONFIG_USER_NS=y
-CONFIG_PID_NS=y
-CONFIG_NET_NS=y
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_SGI_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_CALGARY_IOMMU=y
-CONFIG_AMD_IOMMU=y
-CONFIG_AMD_IOMMU_STATS=y
 CONFIG_NR_CPUS=64
 CONFIG_SCHED_SMT=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -53,27 +55,22 @@ CONFIG_HZ_1000=y
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
 # CONFIG_COMPAT_VDSO is not set
-CONFIG_PM=y
+CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
 CONFIG_PM_TRACE_RTC=y
-CONFIG_HIBERNATION=y
 CONFIG_ACPI_PROCFS=y
 CONFIG_ACPI_DOCK=y
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_DEBUG=y
 # CONFIG_CPU_FREQ_STAT is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_X86_ACPI_CPUFREQ=y
 CONFIG_PCI_MMCONFIG=y
-CONFIG_INTEL_IOMMU=y
-# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCCARD=y
 CONFIG_YENTA=y
 CONFIG_HOTPLUG_PCI=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_BINFMT_MISC=y
 CONFIG_IA32_EMULATION=y
 CONFIG_NET=y
@@ -125,7 +122,6 @@ CONFIG_NF_CONNTRACK_IPV4=y
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_LOG=y
 CONFIG_IP_NF_TARGET_ULOG=y
 CONFIG_NF_NAT=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
@@ -133,7 +129,6 @@ CONFIG_IP_NF_MANGLE=y
 CONFIG_NF_CONNTRACK_IPV6=y
 CONFIG_IP6_NF_IPTABLES=y
 CONFIG_IP6_NF_MATCH_IPV6HEADER=y
-CONFIG_IP6_NF_TARGET_LOG=y
 CONFIG_IP6_NF_FILTER=y
 CONFIG_IP6_NF_TARGET_REJECT=y
 CONFIG_IP6_NF_MANGLE=y
@@ -172,20 +167,15 @@ CONFIG_DM_ZERO=y
 CONFIG_MACINTOSH_DRIVERS=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_VENDOR_3COM=y
+CONFIG_NETCONSOLE=y
+CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
-CONFIG_NET_PCI=y
-CONFIG_FORCEDETH=y
 CONFIG_E100=y
-CONFIG_8139TOO=y
 CONFIG_E1000=y
 CONFIG_SKY2=y
-CONFIG_TIGON3=y
-CONFIG_TR=y
-CONFIG_NET_PCMCIA=y
+CONFIG_FORCEDETH=y
+CONFIG_8139TOO=y
 CONFIG_FDDI=y
-CONFIG_NETCONSOLE=y
 CONFIG_INPUT_POLLDEV=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -194,6 +184,7 @@ CONFIG_INPUT_TABLET=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_MISC=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -203,7 +194,6 @@ CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
-# CONFIG_LEGACY_PTYS is not set
 CONFIG_HW_RANDOM=y
 # CONFIG_HW_RANDOM_INTEL is not set
 # CONFIG_HW_RANDOM_AMD is not set
@@ -221,7 +211,6 @@ CONFIG_DRM_I915_KMS=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_EFI=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
@@ -268,6 +257,10 @@ CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
 CONFIG_DMADEVICES=y
 CONFIG_EEEPC_LAPTOP=y
+CONFIG_AMD_IOMMU=y
+CONFIG_AMD_IOMMU_STATS=y
+CONFIG_INTEL_IOMMU=y
+# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
 CONFIG_EFI_VARS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
@@ -284,7 +277,6 @@ CONFIG_ZISOFS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=y
@@ -292,18 +284,6 @@ CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-CONFIG_MAC_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_SGI_PARTITION=y
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -317,13 +297,12 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUG_RODATA_TEST is not set
 CONFIG_DEBUG_NX_TEST=m
 CONFIG_DEBUG_BOOT_PARAMS=y
index 4c2e59a420b9f64a0f2709aef67188e19f8d3063..d511d951a0527103e05abca9c1cf73b4b024b7c1 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
index 5563ba1cf5136556a618ae345abd0194dc58e75f..a69245ba27e328363de1e389dd5ba50ed2eb979c 100644 (file)
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/kernel.h>
-#include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
-#include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <asm/proto.h>
 #include <asm/vdso.h>
 #include <asm/sigframe.h>
+#include <asm/sighandling.h>
 #include <asm/sys_ia32.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-#define FIX_EFLAGS     (X86_EFLAGS_AC | X86_EFLAGS_OF | \
-                        X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
-                        X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
-                        X86_EFLAGS_CF)
-
-void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
+#define FIX_EFLAGS     __FIX_EFLAGS
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
        int err = 0;
+       bool ia32 = is_ia32_task();
 
        if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
                return -EFAULT;
@@ -75,8 +68,13 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
                        case __SI_FAULT >> 16:
                                break;
                        case __SI_CHLD >> 16:
-                               put_user_ex(from->si_utime, &to->si_utime);
-                               put_user_ex(from->si_stime, &to->si_stime);
+                               if (ia32) {
+                                       put_user_ex(from->si_utime, &to->si_utime);
+                                       put_user_ex(from->si_stime, &to->si_stime);
+                               } else {
+                                       put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
+                                       put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
+                               }
                                put_user_ex(from->si_status, &to->si_status);
                                /* FALL THROUGH */
                        default:
@@ -348,7 +346,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
                put_user_ex(regs->dx, &sc->dx);
                put_user_ex(regs->cx, &sc->cx);
                put_user_ex(regs->ax, &sc->ax);
-               put_user_ex(current->thread.trap_no, &sc->trapno);
+               put_user_ex(current->thread.trap_nr, &sc->trapno);
                put_user_ex(current->thread.error_code, &sc->err);
                put_user_ex(regs->ip, &sc->ip);
                put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
index f6f5c53dc90343e73847a3ae257279a757e016ca..aec2202a596cb0348aa6e5c1b397cff09d3a3386 100644 (file)
@@ -287,46 +287,6 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
        return ret;
 }
 
-asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
-                                    compat_sigset_t __user *oset,
-                                    unsigned int sigsetsize)
-{
-       sigset_t s;
-       compat_sigset_t s32;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-
-       if (set) {
-               if (copy_from_user(&s32, set, sizeof(compat_sigset_t)))
-                       return -EFAULT;
-               switch (_NSIG_WORDS) {
-               case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
-               case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
-               case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
-               case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
-               }
-       }
-       set_fs(KERNEL_DS);
-       ret = sys_rt_sigprocmask(how,
-                                set ? (sigset_t __user *)&s : NULL,
-                                oset ? (sigset_t __user *)&s : NULL,
-                                sigsetsize);
-       set_fs(old_fs);
-       if (ret)
-               return ret;
-       if (oset) {
-               switch (_NSIG_WORDS) {
-               case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
-               case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
-               case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
-               case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
-               }
-               if (copy_to_user(oset, &s32, sizeof(compat_sigset_t)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
 asmlinkage long sys32_alarm(unsigned int seconds)
 {
        return alarm_setitimer(seconds);
index b57e6a43a37a1f9ebca3f4a4966f54b31753e605..f9c0d3ba9e849ef6de5a43b6f32bffacfd73a1db 100644 (file)
@@ -14,6 +14,7 @@ header-y += msr.h
 header-y += mtrr.h
 header-y += posix_types_32.h
 header-y += posix_types_64.h
+header-y += posix_types_x32.h
 header-y += prctl.h
 header-y += processor-flags.h
 header-y += ptrace-abi.h
@@ -24,3 +25,4 @@ header-y += vsyscall.h
 
 genhdr-y += unistd_32.h
 genhdr-y += unistd_64.h
+genhdr-y += unistd_x32.h
index a9371c91718c6a29e9845d12932a6c5239ab6870..d854101712608655a67e10a46ff7b964245798c7 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/atomic.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
-#include <asm/system.h>
 #include <asm/msr.h>
 
 #define ARCH_APICTIMER_STOPS_ON_C3     1
@@ -535,7 +534,7 @@ static inline unsigned int read_apic_id(void)
 
 static inline int default_apic_id_valid(int apicid)
 {
-       return x2apic_mode || (apicid < 255);
+       return (apicid < 255);
 }
 
 extern void default_setup_apic_routing(void);
index 1316b4c3542594cf42024fa98b7cee52afb8b882..77203ac352de1efe74a3b9b2425430510c295a41 100644 (file)
@@ -9,4 +9,11 @@
 #endif
 #define AT_SYSINFO_EHDR                33
 
+/* entries in ARCH_DLINFO: */
+#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64)
+# define AT_VECTOR_SIZE_ARCH 2
+#else /* else it's non-compat x86-64 */
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
 #endif /* _ASM_X86_AUXVEC_H */
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..c6cd358
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef _ASM_X86_BARRIER_H
+#define _ASM_X86_BARRIER_H
+
+#include <asm/alternative.h>
+#include <asm/nops.h>
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+
+#ifdef CONFIG_X86_32
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#else
+#define mb()   asm volatile("mfence":::"memory")
+#define rmb()  asm volatile("lfence":::"memory")
+#define wmb()  asm volatile("sfence" ::: "memory")
+#endif
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     b = 2;
+ *     memory_barrier();
+ *     p = &b;                         q = p;
+ *                                     read_barrier_depends();
+ *                                     d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     a = 2;
+ *     memory_barrier();
+ *     b = 3;                          y = b;
+ *                                     read_barrier_depends();
+ *                                     x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends() do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+# define smp_rmb()     rmb()
+#else
+# define smp_rmb()     barrier()
+#endif
+#ifdef CONFIG_X86_OOSTORE
+# define smp_wmb()     wmb()
+#else
+# define smp_wmb()     barrier()
+#endif
+#define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static __always_inline void rdtsc_barrier(void)
+{
+       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+#endif /* _ASM_X86_BARRIER_H */
index f654d1bb17fb6cf3f0199dd820bd2da2f8b52901..11e1152222d04a18f04803c16826c6bcd0761bd4 100644 (file)
@@ -36,4 +36,8 @@ do {                                                          \
 #endif /* !CONFIG_BUG */
 
 #include <asm-generic/bug.h>
+
+
+extern void show_regs_common(void);
+
 #endif /* _ASM_X86_BUG_H */
index 4e12668711e503659c05dd4b03b436f7926a6cbb..9863ee3747da00c8809042e5beb58738c7b196c4 100644 (file)
@@ -3,6 +3,7 @@
 
 /* Caches aren't brain-dead on the intel. */
 #include <asm-generic/cacheflush.h>
+#include <asm/special_insns.h>
 
 #ifdef CONFIG_X86_PAT
 /*
index 30d737ef2a421e4a457597ae92e28c045f390d0c..d6805798d6fc9e4cad1eedb52cd728cd51cdb8bc 100644 (file)
@@ -6,7 +6,9 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <asm/processor.h>
 #include <asm/user32.h>
+#include <asm/unistd.h>
 
 #define COMPAT_USER_HZ         100
 #define COMPAT_UTS_MACHINE     "i686\0\0"
@@ -186,7 +188,20 @@ struct compat_shmid64_ds {
 /*
  * The type of struct elf_prstatus.pr_reg in compatible core dumps.
  */
+#ifdef CONFIG_X86_X32_ABI
+typedef struct user_regs_struct compat_elf_gregset_t;
+
+#define PR_REG_SIZE(S) (test_thread_flag(TIF_IA32) ? 68 : 216)
+#define PRSTATUS_SIZE(S) (test_thread_flag(TIF_IA32) ? 144 : 296)
+#define SET_PR_FPVALID(S,V) \
+  do { *(int *) (((void *) &((S)->pr_reg)) + PR_REG_SIZE(0)) = (V); } \
+  while (0)
+
+#define COMPAT_USE_64BIT_TIME \
+       (!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT))
+#else
 typedef struct user_regs_struct32 compat_elf_gregset_t;
+#endif
 
 /*
  * A pointer passed in from user mode. This should not
@@ -208,13 +223,30 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
 
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
-       struct pt_regs *regs = task_pt_regs(current);
-       return (void __user *)regs->sp - len;
+       compat_uptr_t sp;
+
+       if (test_thread_flag(TIF_IA32)) {
+               sp = task_pt_regs(current)->sp;
+       } else {
+               /* -128 for the x32 ABI redzone */
+               sp = percpu_read(old_rsp) - 128;
+       }
+
+       return (void __user *)round_down(sp - len, 16);
+}
+
+static inline bool is_x32_task(void)
+{
+#ifdef CONFIG_X86_X32_ABI
+       if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
+               return true;
+#endif
+       return false;
 }
 
-static inline int is_compat_task(void)
+static inline bool is_compat_task(void)
 {
-       return current_thread_info()->status & TS_COMPAT;
+       return is_ia32_task() || is_x32_task();
 }
 
 #endif /* _ASM_X86_COMPAT_H */
index 5f962df30d0f18ed08fe2e321621617d1da39df3..5939f44fe0c0dfdce7fc8a88452e03871be35882 100644 (file)
@@ -84,7 +84,6 @@ extern unsigned int vdso_enabled;
        (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
 
 #include <asm/processor.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_X86_32
 #include <asm/desc.h>
@@ -156,7 +155,12 @@ do {                                               \
 #define elf_check_arch(x)                      \
        ((x)->e_machine == EM_X86_64)
 
-#define compat_elf_check_arch(x)       elf_check_arch_ia32(x)
+#define compat_elf_check_arch(x)               \
+       (elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64)
+
+#if __USER32_DS != __USER_DS
+# error "The following code assumes __USER32_DS == __USER_DS"
+#endif
 
 static inline void elf_common_init(struct thread_struct *t,
                                   struct pt_regs *regs, const u16 ds)
@@ -179,8 +183,9 @@ static inline void elf_common_init(struct thread_struct *t,
 void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp);
 #define compat_start_thread start_thread_ia32
 
-void set_personality_ia32(void);
-#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32()
+void set_personality_ia32(bool);
+#define COMPAT_SET_PERSONALITY(ex)                     \
+       set_personality_ia32((ex).e_machine == EM_X86_64)
 
 #define COMPAT_ELF_PLATFORM                    ("i686")
 
@@ -287,7 +292,7 @@ do {                                                                        \
 #define VDSO_HIGH_BASE         0xffffe000U /* CONFIG_COMPAT_VDSO address */
 
 /* 1GB for 64bit, 8MB for 32bit */
-#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
+#define STACK_RND_MASK (test_thread_flag(TIF_ADDR32) ? 0x7ff : 0x3fffff)
 
 #define ARCH_DLINFO                                                    \
 do {                                                                   \
@@ -296,9 +301,20 @@ do {                                                                       \
                            (unsigned long)current->mm->context.vdso);  \
 } while (0)
 
+#define ARCH_DLINFO_X32                                                        \
+do {                                                                   \
+       if (vdso_enabled)                                               \
+               NEW_AUX_ENT(AT_SYSINFO_EHDR,                            \
+                           (unsigned long)current->mm->context.vdso);  \
+} while (0)
+
 #define AT_SYSINFO             32
 
-#define COMPAT_ARCH_DLINFO     ARCH_DLINFO_IA32(sysctl_vsyscall32)
+#define COMPAT_ARCH_DLINFO                                             \
+if (test_thread_flag(TIF_X32))                                         \
+       ARCH_DLINFO_X32;                                                \
+else                                                                   \
+       ARCH_DLINFO_IA32(sysctl_vsyscall32)
 
 #define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
 
@@ -314,6 +330,8 @@ struct linux_binprm;
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
                                       int uses_interp);
+extern int x32_setup_additional_pages(struct linux_binprm *bprm,
+                                     int uses_interp);
 
 extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
 #define compat_arch_setup_additional_pages     syscall32_setup_pages
@@ -330,7 +348,7 @@ static inline int mmap_is_ia32(void)
        return 1;
 #endif
 #ifdef CONFIG_IA32_EMULATION
-       if (test_thread_flag(TIF_IA32))
+       if (test_thread_flag(TIF_ADDR32))
                return 1;
 #endif
        return 0;
diff --git a/arch/x86/include/asm/exec.h b/arch/x86/include/asm/exec.h
new file mode 100644 (file)
index 0000000..54c2e1d
--- /dev/null
@@ -0,0 +1 @@
+/* define arch_align_stack() here */
index d09bb03653f028e86db69270b9cbb0959adba914..71ecbcba1a4e40abd702030343145e98cfe9961b 100644 (file)
@@ -9,7 +9,6 @@
 #include <asm/asm.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)    \
        asm volatile("1:\t" insn "\n"                           \
index 7ce0798b1b2625c5321dc79a7378f9596d40ae2e..257d9cca214f9470e4be53b06153d82cac398c2b 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/sched.h>
 #include <linux/hardirq.h>
-#include <asm/system.h>
 
 struct pt_regs;
 struct user_i387_struct;
index 1f7e62517284618d6fd08aad123f6e34da8caa26..ee52760549f0797afd660137fbfedeb4cf567b08 100644 (file)
@@ -43,6 +43,15 @@ struct ucontext_ia32 {
        compat_sigset_t   uc_sigmask;   /* mask last for extensibility */
 };
 
+struct ucontext_x32 {
+       unsigned int      uc_flags;
+       unsigned int      uc_link;
+       stack_ia32_t      uc_stack;
+       unsigned int      uc__pad0;     /* needed for alignment */
+       struct sigcontext uc_mcontext;  /* the 64-bit sigcontext type */
+       compat_sigset_t   uc_sigmask;   /* mask last for extensibility */
+};
+
 /* This matches struct stat64 in glibc2.2, hence the absolutely
  * insane amounts of padding around dev_t's.
  */
@@ -116,6 +125,15 @@ typedef struct compat_siginfo {
                        compat_clock_t _stime;
                } _sigchld;
 
+               /* SIGCHLD (x32 version) */
+               struct {
+                       unsigned int _pid;      /* which child */
+                       unsigned int _uid;      /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_s64 _utime;
+                       compat_s64 _stime;
+               } _sigchld_x32;
+
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
                struct {
                        unsigned int _addr;     /* faulting insn/memory ref. */
index f49253d75710e90bd31a86956d941b0cfb289940..c5d1785373ed38c25f1096467d103cd6440c1b66 100644 (file)
@@ -14,6 +14,7 @@ void exit_idle(void);
 #else /* !CONFIG_X86_64 */
 static inline void enter_idle(void) { }
 static inline void exit_idle(void) { }
+static inline void __exit_idle(void) { }
 #endif /* CONFIG_X86_64 */
 
 void amd_e400_remove_cpu(int cpu);
index 690d1cc9a8772c2e3aa457c99503debedbaa3c08..2c4943de5150ee0500f050af0eeaa624c1dfa445 100644 (file)
 #define IO_APIC_REDIR_LEVEL_TRIGGER    (1 << 15)
 #define IO_APIC_REDIR_MASKED           (1 << 16)
 
+struct io_apic_ops {
+       void            (*init)  (void);
+       unsigned int    (*read)  (unsigned int apic, unsigned int reg);
+       void            (*write) (unsigned int apic, unsigned int reg, unsigned int value);
+       void            (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
+};
+
+void __init set_io_apic_ops(const struct io_apic_ops *);
+
 /*
  * The structure of the IO-APIC:
  */
index 4d8dcbdfc1205956c3b90b6f13d6bff021b63860..e7d1c194d27280381ae302f9d1aac2d69a872b2e 100644 (file)
@@ -321,4 +321,8 @@ struct kvm_xcrs {
        __u64 padding[16];
 };
 
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
 #endif /* _ASM_X86_KVM_H */
index 7b9cfc4878afc374dacb4852312be4fcba35384e..c222e1a1b12addc1260929dbaaf86c5102f95eda 100644 (file)
@@ -176,6 +176,7 @@ struct x86_emulate_ops {
        void (*set_idt)(struct x86_emulate_ctxt *ctxt, struct desc_ptr *dt);
        ulong (*get_cr)(struct x86_emulate_ctxt *ctxt, int cr);
        int (*set_cr)(struct x86_emulate_ctxt *ctxt, int cr, ulong val);
+       void (*set_rflags)(struct x86_emulate_ctxt *ctxt, ulong val);
        int (*cpl)(struct x86_emulate_ctxt *ctxt);
        int (*get_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong *dest);
        int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
@@ -388,7 +389,7 @@ bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt);
 #define EMULATION_INTERCEPTED 2
 int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
-                        u16 tss_selector, int reason,
+                        u16 tss_selector, int idt_index, int reason,
                         bool has_error_code, u32 error_code);
 int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq);
 #endif /* _ASM_X86_KVM_X86_EMULATE_H */
index 52d6640a5ca1eec731418d408fc6e03c161ce3fe..e216ba066e798cbd7be31892ac76afcc78055c0b 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/msr-index.h>
 
 #define KVM_MAX_VCPUS 254
-#define KVM_SOFT_MAX_VCPUS 64
+#define KVM_SOFT_MAX_VCPUS 160
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
@@ -181,13 +181,6 @@ struct kvm_mmu_memory_cache {
        void *objects[KVM_NR_MEM_OBJS];
 };
 
-#define NR_PTE_CHAIN_ENTRIES 5
-
-struct kvm_pte_chain {
-       u64 *parent_ptes[NR_PTE_CHAIN_ENTRIES];
-       struct hlist_node link;
-};
-
 /*
  * kvm_mmu_page_role, below, is defined as:
  *
@@ -427,12 +420,16 @@ struct kvm_vcpu_arch {
 
        u64 last_guest_tsc;
        u64 last_kernel_ns;
-       u64 last_tsc_nsec;
-       u64 last_tsc_write;
-       u32 virtual_tsc_khz;
+       u64 last_host_tsc;
+       u64 tsc_offset_adjustment;
+       u64 this_tsc_nsec;
+       u64 this_tsc_write;
+       u8  this_tsc_generation;
        bool tsc_catchup;
-       u32  tsc_catchup_mult;
-       s8   tsc_catchup_shift;
+       bool tsc_always_catchup;
+       s8 virtual_tsc_shift;
+       u32 virtual_tsc_mult;
+       u32 virtual_tsc_khz;
 
        atomic_t nmi_queued;  /* unprocessed asynchronous NMIs */
        unsigned nmi_pending; /* NMI queued after currently running handler */
@@ -478,6 +475,21 @@ struct kvm_vcpu_arch {
                u32 id;
                bool send_user_only;
        } apf;
+
+       /* OSVW MSRs (AMD only) */
+       struct {
+               u64 length;
+               u64 status;
+       } osvw;
+};
+
+struct kvm_lpage_info {
+       unsigned long rmap_pde;
+       int write_count;
+};
+
+struct kvm_arch_memory_slot {
+       struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
 };
 
 struct kvm_arch {
@@ -511,8 +523,12 @@ struct kvm_arch {
        s64 kvmclock_offset;
        raw_spinlock_t tsc_write_lock;
        u64 last_tsc_nsec;
-       u64 last_tsc_offset;
        u64 last_tsc_write;
+       u32 last_tsc_khz;
+       u64 cur_tsc_nsec;
+       u64 cur_tsc_write;
+       u64 cur_tsc_offset;
+       u8  cur_tsc_generation;
 
        struct kvm_xen_hvm_config xen_hvm_config;
 
@@ -644,7 +660,7 @@ struct kvm_x86_ops {
        u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
        int (*get_lpage_level)(void);
        bool (*rdtscp_supported)(void);
-       void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment);
+       void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment, bool host);
 
        void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
 
@@ -652,7 +668,7 @@ struct kvm_x86_ops {
 
        bool (*has_wbinvd_exit)(void);
 
-       void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz);
+       void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale);
        void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
        u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
@@ -674,6 +690,17 @@ struct kvm_arch_async_pf {
 
 extern struct kvm_x86_ops *kvm_x86_ops;
 
+static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
+                                          s64 adjustment)
+{
+       kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, false);
+}
+
+static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
+{
+       kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, true);
+}
+
 int kvm_mmu_module_init(void);
 void kvm_mmu_module_exit(void);
 
@@ -741,8 +768,8 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
 void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
 int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
 
-int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
-                   bool has_error_code, u32 error_code);
+int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
+                   int reason, bool has_error_code, u32 error_code);
 
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
index 9cdae5d47e8fad287dfdde2e27e2900b0ff30405..c8bed0da434a40dcd23ef16ecd518fa9cc164bc1 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/percpu.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/asm.h>
 
index 0e8e85bb7c51bc57fd87bebeb6727e675ebe1c8f..d354fb781c5793ec5a69a63dfc5d05a3a6aa6948 100644 (file)
@@ -5,7 +5,6 @@
 #define _ASM_X86_MC146818RTC_H
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <linux/mc146818rtc.h>
 
index 4365ffdb461f52b946b8e71c5ffa6c250d7f12be..7e3f17f92c665ec79850eefa328567e06c50134c 100644 (file)
 
 #define        MTRR_IOCTL_BASE 'M'
 
-struct mtrr_sentry {
-    unsigned long base;    /*  Base address     */
-    unsigned int size;    /*  Size of region   */
-    unsigned int type;     /*  Type of region   */
-};
-
 /* Warning: this structure has a different order from i386
    on x86-64. The 32bit emulation code takes care of that.
    But you need to use this for 64bit, otherwise your X server
    will break. */
 
 #ifdef __i386__
+struct mtrr_sentry {
+    unsigned long base;    /*  Base address     */
+    unsigned int size;    /*  Size of region   */
+    unsigned int type;     /*  Type of region   */
+};
+
 struct mtrr_gentry {
     unsigned int regnum;   /*  Register number  */
     unsigned long base;    /*  Base address     */
@@ -50,12 +50,20 @@ struct mtrr_gentry {
 
 #else /* __i386__ */
 
+struct mtrr_sentry {
+       __u64 base;             /*  Base address     */
+       __u32 size;             /*  Size of region   */
+       __u32 type;             /*  Type of region   */
+};
+
 struct mtrr_gentry {
-    unsigned long base;    /*  Base address     */
-    unsigned int size;    /*  Size of region   */
-    unsigned int regnum;   /*  Register number  */
-    unsigned int type;     /*  Type of region   */
+       __u64 base;             /*  Base address     */
+       __u32 size;             /*  Size of region   */
+       __u32 regnum;           /*  Register number  */
+       __u32 type;             /*  Type of region   */
+       __u32 _pad;             /*  Unused           */
 };
+
 #endif /* !__i386__ */
 
 struct mtrr_var_range {
index bce688d54c12383e29b360bb7688b3fc9d385830..e21fdd10479f88e339e1e7351da837c563361635 100644 (file)
@@ -55,7 +55,6 @@ extern unsigned long init_memory_mapping(unsigned long start,
                                         unsigned long end);
 
 extern void initmem_init(void);
-extern void free_initmem(void);
 
 #endif /* !__ASSEMBLY__ */
 
index e8fb2c7a5f4ff1792c16dc1c8df498a0801b8eed..2291895b1836a4acf9b9313722fb670717f0d4c5 100644 (file)
@@ -23,6 +23,7 @@
 #define ARCH_PERFMON_EVENTSEL_USR                      (1ULL << 16)
 #define ARCH_PERFMON_EVENTSEL_OS                       (1ULL << 17)
 #define ARCH_PERFMON_EVENTSEL_EDGE                     (1ULL << 18)
+#define ARCH_PERFMON_EVENTSEL_PIN_CONTROL              (1ULL << 19)
 #define ARCH_PERFMON_EVENTSEL_INT                      (1ULL << 20)
 #define ARCH_PERFMON_EVENTSEL_ANY                      (1ULL << 21)
 #define ARCH_PERFMON_EVENTSEL_ENABLE                   (1ULL << 22)
index bb7133dc155d4bebb9094693a8b823d4ae127e19..3427b7798dbcdfed5a93f0e5d448feedb588846c 100644 (file)
@@ -7,7 +7,9 @@
 #else
 # ifdef __i386__
 #  include "posix_types_32.h"
-# else
+# elif defined(__LP64__)
 #  include "posix_types_64.h"
+# else
+#  include "posix_types_x32.h"
 # endif
 #endif
index f7d9adf82e5396cce337b7e62d0821371361bdc9..99f262e04b91b6d553fd65bd61957bd9cb5cbd15 100644 (file)
@@ -7,79 +7,22 @@
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
 typedef unsigned short __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
 typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned short __kernel_uid_t;
 typedef unsigned short __kernel_gid_t;
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
+#define __kernel_uid_t __kernel_uid_t
 
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
 typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-#define __FD_SET(fd,fdsetp)                                    \
-       asm volatile("btsl %1,%0":                              \
-                    "+m" (*(__kernel_fd_set *)(fdsetp))        \
-                    : "r" ((int)(fd)))
-
-#undef __FD_CLR
-#define __FD_CLR(fd,fdsetp)                                    \
-       asm volatile("btrl %1,%0":                              \
-                    "+m" (*(__kernel_fd_set *)(fdsetp))        \
-                    : "r" ((int) (fd)))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd,fdsetp)                                  \
-       (__extension__                                          \
-        ({                                                     \
-        unsigned char __result;                                \
-        asm volatile("btl %1,%2 ; setb %0"                     \
-                     : "=q" (__result)                         \
-                     : "r" ((int)(fd)),                        \
-                       "m" (*(__kernel_fd_set *)(fdsetp)));    \
-        __result;                                              \
-}))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp)                                      \
-do {                                                           \
-       int __d0, __d1;                                         \
-       asm volatile("cld ; rep ; stosl"                        \
-                    : "=m" (*(__kernel_fd_set *)(fdsetp)),     \
-                      "=&c" (__d0), "=&D" (__d1)               \
-                    : "a" (0), "1" (__FDSET_LONGS),            \
-                      "2" ((__kernel_fd_set *)(fdsetp))        \
-                    : "memory");                               \
-} while (0)
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ASM_X86_POSIX_TYPES_32_H */
index eb8d2d92b63e6e7a5cbad9b472d0f607a4c22a69..cba0c1ead162834d56b3a6c945f5b98d1d10f028 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
-typedef unsigned int   __kernel_mode_t;
-typedef unsigned long  __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
-typedef int            __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
-typedef long           __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
 typedef unsigned short __kernel_old_uid_t;
 typedef unsigned short __kernel_old_gid_t;
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
 
 typedef unsigned long  __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-#ifdef __KERNEL__
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
-       unsigned long *tmp = p->fds_bits;
-       int i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-               case 32:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-                       tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                       tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
-                       tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
-                       tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
-                       tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
-                       return;
-               case 16:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-                       tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-                       return;
-               case 8:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-                       return;
-               case 4:
-                       tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-                       return;
-               }
-       }
-       i = __FDSET_LONGS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ASM_X86_POSIX_TYPES_64_H */
diff --git a/arch/x86/include/asm/posix_types_x32.h b/arch/x86/include/asm/posix_types_x32.h
new file mode 100644 (file)
index 0000000..85f9bda
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_X86_POSIX_TYPES_X32_H
+#define _ASM_X86_POSIX_TYPES_X32_H
+
+/*
+ * This file is only used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ *
+ * These types should generally match the ones used by the 64-bit kernel,
+ *
+ */
+
+typedef long long __kernel_long_t;
+typedef unsigned long long __kernel_ulong_t;
+#define __kernel_long_t __kernel_long_t
+
+#include <asm/posix_types_64.h>
+
+#endif /* _ASM_X86_POSIX_TYPES_X32_H */
index 5533b30cac0719f77f674926d85f055ca59dc943..7284c9a6a0b531c29132a475b0429046787de742 100644 (file)
@@ -14,13 +14,13 @@ struct mm_struct;
 #include <asm/sigcontext.h>
 #include <asm/current.h>
 #include <asm/cpufeature.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable_types.h>
 #include <asm/percpu.h>
 #include <asm/msr.h>
 #include <asm/desc_defs.h>
 #include <asm/nops.h>
+#include <asm/special_insns.h>
 
 #include <linux/personality.h>
 #include <linux/cpumask.h>
@@ -29,6 +29,15 @@ struct mm_struct;
 #include <linux/math64.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/irqflags.h>
+
+/*
+ * We handle most unaligned accesses in hardware.  On the other hand
+ * unaligned DMA can be quite expensive on some Nehalem processors.
+ *
+ * Based on this we disable the IP header alignment in network drivers.
+ */
+#define NET_IP_ALIGN   0
 
 #define HBP_NUM 4
 /*
@@ -454,7 +463,7 @@ struct thread_struct {
        unsigned long           ptrace_dr7;
        /* Fault info: */
        unsigned long           cr2;
-       unsigned long           trap_no;
+       unsigned long           trap_nr;
        unsigned long           error_code;
        /* floating point and extended processor state */
        struct fpu              fpu;
@@ -864,9 +873,9 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
 #define IA32_PAGE_OFFSET       ((current->personality & ADDR_LIMIT_3GB) ? \
                                        0xc0000000 : 0xFFFFe000)
 
-#define TASK_SIZE              (test_thread_flag(TIF_IA32) ? \
+#define TASK_SIZE              (test_thread_flag(TIF_ADDR32) ? \
                                        IA32_PAGE_OFFSET : TASK_SIZE_MAX)
-#define TASK_SIZE_OF(child)    ((test_tsk_thread_flag(child, TIF_IA32)) ? \
+#define TASK_SIZE_OF(child)    ((test_tsk_thread_flag(child, TIF_ADDR32)) ? \
                                        IA32_PAGE_OFFSET : TASK_SIZE_MAX)
 
 #define STACK_TOP              TASK_SIZE
@@ -888,6 +897,12 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 #define task_pt_regs(tsk)      ((struct pt_regs *)(tsk)->thread.sp0 - 1)
 extern unsigned long KSTK_ESP(struct task_struct *task);
+
+/*
+ * User space RSP while inside the SYSCALL fast path
+ */
+DECLARE_PER_CPU(unsigned long, old_rsp);
+
 #endif /* CONFIG_X86_64 */
 
 extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
@@ -959,4 +974,24 @@ extern bool cpu_has_amd_erratum(const int *);
 #define cpu_has_amd_erratum(x) (false)
 #endif /* CONFIG_CPU_SUP_AMD */
 
+#ifdef CONFIG_X86_32
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+#endif
+
+void disable_hlt(void);
+void enable_hlt(void);
+
+void cpu_idle_wait(void);
+
+extern unsigned long arch_align_stack(unsigned long sp);
+extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+
+void default_idle(void);
+bool set_pm_idle_to_default(void);
+
+void stop_this_cpu(void *dummy);
+
 #endif /* _ASM_X86_PROCESSOR_H */
index 35664547125b40f663d09c3e556f7699e630586b..dcfde52979c3e63be0d42627cc567cf76c733090 100644 (file)
@@ -145,7 +145,6 @@ extern unsigned long
 convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
                         int error_code, int si_code);
-void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 extern long syscall_trace_enter(struct pt_regs *);
 extern void syscall_trace_leave(struct pt_regs *);
index 5e641715c3fea5f0b518624ab5d9c11b9d474bdc..165466233ab0376192d94b6cd6a8d327a4c22d00 100644 (file)
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10];
-#endif
-#endif
+
+/*
+ * Load a segment. Fall back on loading the zero
+ * segment if something goes wrong..
+ */
+#define loadsegment(seg, value)                                                \
+do {                                                                   \
+       unsigned short __val = (value);                                 \
+                                                                       \
+       asm volatile("                                          \n"     \
+                    "1:        movl %k0,%%" #seg "             \n"     \
+                                                                       \
+                    ".section .fixup,\"ax\"                    \n"     \
+                    "2:        xorl %k0,%k0                    \n"     \
+                    "          jmp 1b                          \n"     \
+                    ".previous                                 \n"     \
+                                                                       \
+                    _ASM_EXTABLE(1b, 2b)                               \
+                                                                       \
+                    : "+r" (__val) : : "memory");                      \
+} while (0)
+
+/*
+ * Save a segment register away
+ */
+#define savesegment(seg, value)                                \
+       asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+
+/*
+ * x86_32 user gs accessors.
+ */
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_32_LAZY_GS
+#define get_user_gs(regs)      (u16)({unsigned long v; savesegment(gs, v); v;})
+#define set_user_gs(regs, v)   loadsegment(gs, (unsigned long)(v))
+#define task_user_gs(tsk)      ((tsk)->thread.gs)
+#define lazy_save_gs(v)                savesegment(gs, (v))
+#define lazy_load_gs(v)                loadsegment(gs, (v))
+#else  /* X86_32_LAZY_GS */
+#define get_user_gs(regs)      (u16)((regs)->gs)
+#define set_user_gs(regs, v)   do { (regs)->gs = (v); } while (0)
+#define task_user_gs(tsk)      (task_pt_regs(tsk)->gs)
+#define lazy_save_gs(v)                do { } while (0)
+#define lazy_load_gs(v)                do { } while (0)
+#endif /* X86_32_LAZY_GS */
+#endif /* X86_32 */
+
+static inline unsigned long get_limit(unsigned long segment)
+{
+       unsigned long __limit;
+       asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
+       return __limit + 1;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_SEGMENT_H */
index 04459d25e66e50027829eb873e11751309821fc8..4a085383af27effcab8935689ef63f0ba9304842 100644 (file)
@@ -230,34 +230,37 @@ struct sigcontext {
  * User-space might still rely on the old definition:
  */
 struct sigcontext {
-       unsigned long r8;
-       unsigned long r9;
-       unsigned long r10;
-       unsigned long r11;
-       unsigned long r12;
-       unsigned long r13;
-       unsigned long r14;
-       unsigned long r15;
-       unsigned long rdi;
-       unsigned long rsi;
-       unsigned long rbp;
-       unsigned long rbx;
-       unsigned long rdx;
-       unsigned long rax;
-       unsigned long rcx;
-       unsigned long rsp;
-       unsigned long rip;
-       unsigned long eflags;           /* RFLAGS */
-       unsigned short cs;
-       unsigned short gs;
-       unsigned short fs;
-       unsigned short __pad0;
-       unsigned long err;
-       unsigned long trapno;
-       unsigned long oldmask;
-       unsigned long cr2;
+       __u64 r8;
+       __u64 r9;
+       __u64 r10;
+       __u64 r11;
+       __u64 r12;
+       __u64 r13;
+       __u64 r14;
+       __u64 r15;
+       __u64 rdi;
+       __u64 rsi;
+       __u64 rbp;
+       __u64 rbx;
+       __u64 rdx;
+       __u64 rax;
+       __u64 rcx;
+       __u64 rsp;
+       __u64 rip;
+       __u64 eflags;           /* RFLAGS */
+       __u16 cs;
+       __u16 gs;
+       __u16 fs;
+       __u16 __pad0;
+       __u64 err;
+       __u64 trapno;
+       __u64 oldmask;
+       __u64 cr2;
        struct _fpstate __user *fpstate;        /* zero when no FPU context */
-       unsigned long reserved1[8];
+#ifndef __LP64__
+       __u32 __fpstate_pad;
+#endif
+       __u64 reserved1[8];
 };
 #endif /* !__KERNEL__ */
 
index 4e0fe26d27d341005a43f4d62608b57a1c33498b..7c7c27c97daa1077cb4b5a1cca2c229debd1707c 100644 (file)
@@ -59,12 +59,25 @@ struct rt_sigframe_ia32 {
 #endif /* defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) */
 
 #ifdef CONFIG_X86_64
+
 struct rt_sigframe {
        char __user *pretcode;
        struct ucontext uc;
        struct siginfo info;
        /* fp state follows here */
 };
+
+#ifdef CONFIG_X86_X32_ABI
+
+struct rt_sigframe_x32 {
+       u64 pretcode;
+       struct ucontext_x32 uc;
+       compat_siginfo_t info;
+       /* fp state follows here */
+};
+
+#endif /* CONFIG_X86_X32_ABI */
+
 #endif /* CONFIG_X86_64 */
 
 #endif /* _ASM_X86_SIGFRAME_H */
diff --git a/arch/x86/include/asm/sighandling.h b/arch/x86/include/asm/sighandling.h
new file mode 100644 (file)
index 0000000..ada93b3
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _ASM_X86_SIGHANDLING_H
+#define _ASM_X86_SIGHANDLING_H
+
+#include <linux/compiler.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+
+#include <asm/processor-flags.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+#define __FIX_EFLAGS   (X86_EFLAGS_AC | X86_EFLAGS_OF | \
+                        X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
+                        X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
+                        X86_EFLAGS_CF)
+
+void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
+
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
+                      unsigned long *pax);
+int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
+                    struct pt_regs *regs, unsigned long mask);
+
+#endif /* _ASM_X86_SIGHANDLING_H */
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..41fc93a
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef _ASM_X86_SPECIAL_INSNS_H
+#define _ASM_X86_SPECIAL_INSNS_H
+
+
+#ifdef __KERNEL__
+
+static inline void native_clts(void)
+{
+       asm volatile("clts");
+}
+
+/*
+ * Volatile isn't enough to prevent the compiler from reordering the
+ * read/write functions for the control registers and messing everything up.
+ * A memory clobber would solve the problem, but would prevent reordering of
+ * all loads stores around it, which can hurt performance. Solution is to
+ * use a variable and mimic reads and writes to it to enforce serialization
+ */
+static unsigned long __force_order;
+
+static inline unsigned long native_read_cr0(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline void native_write_cr0(unsigned long val)
+{
+       asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long native_read_cr2(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline void native_write_cr2(unsigned long val)
+{
+       asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long native_read_cr3(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline void native_write_cr3(unsigned long val)
+{
+       asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long native_read_cr4(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline unsigned long native_read_cr4_safe(void)
+{
+       unsigned long val;
+       /* This could fault if %cr4 does not exist. In x86_64, a cr4 always
+        * exists, so it will never fail. */
+#ifdef CONFIG_X86_32
+       asm volatile("1: mov %%cr4, %0\n"
+                    "2:\n"
+                    _ASM_EXTABLE(1b, 2b)
+                    : "=r" (val), "=m" (__force_order) : "0" (0));
+#else
+       val = native_read_cr4();
+#endif
+       return val;
+}
+
+static inline void native_write_cr4(unsigned long val)
+{
+       asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
+}
+
+#ifdef CONFIG_X86_64
+static inline unsigned long native_read_cr8(void)
+{
+       unsigned long cr8;
+       asm volatile("movq %%cr8,%0" : "=r" (cr8));
+       return cr8;
+}
+
+static inline void native_write_cr8(unsigned long val)
+{
+       asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
+}
+#endif
+
+static inline void native_wbinvd(void)
+{
+       asm volatile("wbinvd": : :"memory");
+}
+
+extern void native_load_gs_index(unsigned);
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+
+static inline unsigned long read_cr0(void)
+{
+       return native_read_cr0();
+}
+
+static inline void write_cr0(unsigned long x)
+{
+       native_write_cr0(x);
+}
+
+static inline unsigned long read_cr2(void)
+{
+       return native_read_cr2();
+}
+
+static inline void write_cr2(unsigned long x)
+{
+       native_write_cr2(x);
+}
+
+static inline unsigned long read_cr3(void)
+{
+       return native_read_cr3();
+}
+
+static inline void write_cr3(unsigned long x)
+{
+       native_write_cr3(x);
+}
+
+static inline unsigned long read_cr4(void)
+{
+       return native_read_cr4();
+}
+
+static inline unsigned long read_cr4_safe(void)
+{
+       return native_read_cr4_safe();
+}
+
+static inline void write_cr4(unsigned long x)
+{
+       native_write_cr4(x);
+}
+
+static inline void wbinvd(void)
+{
+       native_wbinvd();
+}
+
+#ifdef CONFIG_X86_64
+
+static inline unsigned long read_cr8(void)
+{
+       return native_read_cr8();
+}
+
+static inline void write_cr8(unsigned long x)
+{
+       native_write_cr8(x);
+}
+
+static inline void load_gs_index(unsigned selector)
+{
+       native_load_gs_index(selector);
+}
+
+#endif
+
+/* Clear the 'TS' bit */
+static inline void clts(void)
+{
+       native_clts();
+}
+
+#endif/* CONFIG_PARAVIRT */
+
+#define stts() write_cr0(read_cr0() | X86_CR0_TS)
+
+static inline void clflush(volatile void *__p)
+{
+       asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
+}
+
+#define nop() asm volatile ("nop")
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_X86_SPECIAL_INSNS_H */
index 157517763565668d050a628f98630199764d825c..b5d9533d2c38f4e78485256ec9ba07497e93057e 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/tsc.h>
 #include <asm/processor.h>
 #include <asm/percpu.h>
-#include <asm/system.h>
 #include <asm/desc.h>
 #include <linux/random.h>
 
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..4ec45b3
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _ASM_X86_SWITCH_TO_H
+#define _ASM_X86_SWITCH_TO_H
+
+struct task_struct; /* one of the stranger aspects of C forward declarations */
+struct task_struct *__switch_to(struct task_struct *prev,
+                               struct task_struct *next);
+struct tss_struct;
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+                     struct tss_struct *tss);
+
+#ifdef CONFIG_X86_32
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+#define __switch_canary                                                        \
+       "movl %P[task_canary](%[next]), %%ebx\n\t"                      \
+       "movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
+#define __switch_canary_oparam                                         \
+       , [stack_canary] "=m" (stack_canary.canary)
+#define __switch_canary_iparam                                         \
+       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+#else  /* CC_STACKPROTECTOR */
+#define __switch_canary
+#define __switch_canary_oparam
+#define __switch_canary_iparam
+#endif /* CC_STACKPROTECTOR */
+
+/*
+ * Saving eflags is important. It switches not only IOPL between tasks,
+ * it also protects other tasks from NT leaking through sysenter etc.
+ */
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       /*                                                              \
+        * Context-switching clobbers all registers, so we clobber      \
+        * them explicitly, via unused output variables.                \
+        * (EAX and EBP is not listed because EBP is saved/restored     \
+        * explicitly for wchan access and EAX is the return value of   \
+        * __switch_to())                                               \
+        */                                                             \
+       unsigned long ebx, ecx, edx, esi, edi;                          \
+                                                                       \
+       asm volatile("pushfl\n\t"               /* save    flags */     \
+                    "pushl %%ebp\n\t"          /* save    EBP   */     \
+                    "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
+                    "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
+                    "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
+                    "pushl %[next_ip]\n\t"     /* restore EIP   */     \
+                    __switch_canary                                    \
+                    "jmp __switch_to\n"        /* regparm call  */     \
+                    "1:\t"                                             \
+                    "popl %%ebp\n\t"           /* restore EBP   */     \
+                    "popfl\n"                  /* restore flags */     \
+                                                                       \
+                    /* output parameters */                            \
+                    : [prev_sp] "=m" (prev->thread.sp),                \
+                      [prev_ip] "=m" (prev->thread.ip),                \
+                      "=a" (last),                                     \
+                                                                       \
+                      /* clobbered output registers: */                \
+                      "=b" (ebx), "=c" (ecx), "=d" (edx),              \
+                      "=S" (esi), "=D" (edi)                           \
+                                                                       \
+                      __switch_canary_oparam                           \
+                                                                       \
+                      /* input parameters: */                          \
+                    : [next_sp]  "m" (next->thread.sp),                \
+                      [next_ip]  "m" (next->thread.ip),                \
+                                                                       \
+                      /* regparm parameters for __switch_to(): */      \
+                      [prev]     "a" (prev),                           \
+                      [next]     "d" (next)                            \
+                                                                       \
+                      __switch_canary_iparam                           \
+                                                                       \
+                    : /* reloaded segment registers */                 \
+                       "memory");                                      \
+} while (0)
+
+#else /* CONFIG_X86_32 */
+
+/* frame pointer must be last for get_wchan */
+#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
+
+#define __EXTRA_CLOBBER  \
+       , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
+         "r12", "r13", "r14", "r15"
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+#define __switch_canary                                                          \
+       "movq %P[task_canary](%%rsi),%%r8\n\t"                            \
+       "movq %%r8,"__percpu_arg([gs_canary])"\n\t"
+#define __switch_canary_oparam                                           \
+       , [gs_canary] "=m" (irq_stack_union.stack_canary)
+#define __switch_canary_iparam                                           \
+       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+#else  /* CC_STACKPROTECTOR */
+#define __switch_canary
+#define __switch_canary_oparam
+#define __switch_canary_iparam
+#endif /* CC_STACKPROTECTOR */
+
+/* Save restore flags to clear handle leaking NT */
+#define switch_to(prev, next, last) \
+       asm volatile(SAVE_CONTEXT                                         \
+            "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
+            "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
+            "call __switch_to\n\t"                                       \
+            "movq "__percpu_arg([current_task])",%%rsi\n\t"              \
+            __switch_canary                                              \
+            "movq %P[thread_info](%%rsi),%%r8\n\t"                       \
+            "movq %%rax,%%rdi\n\t"                                       \
+            "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"                 \
+            "jnz   ret_from_fork\n\t"                                    \
+            RESTORE_CONTEXT                                              \
+            : "=a" (last)                                                \
+              __switch_canary_oparam                                     \
+            : [next] "S" (next), [prev] "D" (prev),                      \
+              [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
+              [ti_flags] "i" (offsetof(struct thread_info, flags)),      \
+              [_tif_fork] "i" (_TIF_FORK),                               \
+              [thread_info] "i" (offsetof(struct task_struct, stack)),   \
+              [current_task] "m" (current_task)                          \
+              __switch_canary_iparam                                     \
+            : "memory", "cc" __EXTRA_CLOBBER)
+
+#endif /* CONFIG_X86_32 */
+
+#endif /* _ASM_X86_SWITCH_TO_H */
index cb238526a9f12959ebed76a6d76d0d9e750a17bd..3fda9db488199c0b073e66ab7e1aded2e030620e 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef _ASM_X86_SYS_IA32_H
 #define _ASM_X86_SYS_IA32_H
 
+#ifdef CONFIG_COMPAT
+
 #include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
@@ -36,8 +38,6 @@ asmlinkage long sys32_rt_sigaction(int, struct sigaction32 __user *,
                                   struct sigaction32 __user *, unsigned int);
 asmlinkage long sys32_sigaction(int, struct old_sigaction32 __user *,
                                struct old_sigaction32 __user *);
-asmlinkage long sys32_rt_sigprocmask(int, compat_sigset_t __user *,
-                                    compat_sigset_t __user *, unsigned int);
 asmlinkage long sys32_alarm(unsigned int);
 
 asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int);
@@ -83,4 +83,7 @@ asmlinkage long sys32_ipc(u32, int, int, int, compat_uptr_t, u32);
 
 asmlinkage long sys32_fanotify_mark(int, unsigned int, u32, u32, int,
                                    const char __user *);
+
+#endif /* CONFIG_COMPAT */
+
 #endif /* _ASM_X86_SYS_IA32_H */
index d962e5652a7352498bd9654315f7819fb7d9d86b..386b78686c4d9e9d096e9dbf215541003eec0837 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/err.h>
 #include <asm/asm-offsets.h>   /* For NR_syscalls */
+#include <asm/unistd.h>
 
 extern const unsigned long sys_call_table[];
 
@@ -26,13 +27,13 @@ extern const unsigned long sys_call_table[];
  */
 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
-       return regs->orig_ax;
+       return regs->orig_ax & __SYSCALL_MASK;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
-       regs->ax = regs->orig_ax;
+       regs->ax = regs->orig_ax & __SYSCALL_MASK;
 }
 
 static inline long syscall_get_error(struct task_struct *task,
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
deleted file mode 100644 (file)
index 2d2f01c..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H
-#define _ASM_X86_SYSTEM_H
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64)
-# define AT_VECTOR_SIZE_ARCH 2
-#else /* else it's non-compat x86-64 */
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-struct task_struct; /* one of the stranger aspects of C forward declarations */
-struct task_struct *__switch_to(struct task_struct *prev,
-                               struct task_struct *next);
-struct tss_struct;
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss);
-extern void show_regs_common(void);
-
-#ifdef CONFIG_X86_32
-
-#ifdef CONFIG_CC_STACKPROTECTOR
-#define __switch_canary                                                        \
-       "movl %P[task_canary](%[next]), %%ebx\n\t"                      \
-       "movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
-#define __switch_canary_oparam                                         \
-       , [stack_canary] "=m" (stack_canary.canary)
-#define __switch_canary_iparam                                         \
-       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
-#else  /* CC_STACKPROTECTOR */
-#define __switch_canary
-#define __switch_canary_oparam
-#define __switch_canary_iparam
-#endif /* CC_STACKPROTECTOR */
-
-/*
- * Saving eflags is important. It switches not only IOPL between tasks,
- * it also protects other tasks from NT leaking through sysenter etc.
- */
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       /*                                                              \
-        * Context-switching clobbers all registers, so we clobber      \
-        * them explicitly, via unused output variables.                \
-        * (EAX and EBP is not listed because EBP is saved/restored     \
-        * explicitly for wchan access and EAX is the return value of   \
-        * __switch_to())                                               \
-        */                                                             \
-       unsigned long ebx, ecx, edx, esi, edi;                          \
-                                                                       \
-       asm volatile("pushfl\n\t"               /* save    flags */     \
-                    "pushl %%ebp\n\t"          /* save    EBP   */     \
-                    "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
-                    "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
-                    "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
-                    "pushl %[next_ip]\n\t"     /* restore EIP   */     \
-                    __switch_canary                                    \
-                    "jmp __switch_to\n"        /* regparm call  */     \
-                    "1:\t"                                             \
-                    "popl %%ebp\n\t"           /* restore EBP   */     \
-                    "popfl\n"                  /* restore flags */     \
-                                                                       \
-                    /* output parameters */                            \
-                    : [prev_sp] "=m" (prev->thread.sp),                \
-                      [prev_ip] "=m" (prev->thread.ip),                \
-                      "=a" (last),                                     \
-                                                                       \
-                      /* clobbered output registers: */                \
-                      "=b" (ebx), "=c" (ecx), "=d" (edx),              \
-                      "=S" (esi), "=D" (edi)                           \
-                                                                       \
-                      __switch_canary_oparam                           \
-                                                                       \
-                      /* input parameters: */                          \
-                    : [next_sp]  "m" (next->thread.sp),                \
-                      [next_ip]  "m" (next->thread.ip),                \
-                                                                       \
-                      /* regparm parameters for __switch_to(): */      \
-                      [prev]     "a" (prev),                           \
-                      [next]     "d" (next)                            \
-                                                                       \
-                      __switch_canary_iparam                           \
-                                                                       \
-                    : /* reloaded segment registers */                 \
-                       "memory");                                      \
-} while (0)
-
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-#else
-
-/* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
-
-#define __EXTRA_CLOBBER  \
-       , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
-         "r12", "r13", "r14", "r15"
-
-#ifdef CONFIG_CC_STACKPROTECTOR
-#define __switch_canary                                                          \
-       "movq %P[task_canary](%%rsi),%%r8\n\t"                            \
-       "movq %%r8,"__percpu_arg([gs_canary])"\n\t"
-#define __switch_canary_oparam                                           \
-       , [gs_canary] "=m" (irq_stack_union.stack_canary)
-#define __switch_canary_iparam                                           \
-       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
-#else  /* CC_STACKPROTECTOR */
-#define __switch_canary
-#define __switch_canary_oparam
-#define __switch_canary_iparam
-#endif /* CC_STACKPROTECTOR */
-
-/* Save restore flags to clear handle leaking NT */
-#define switch_to(prev, next, last) \
-       asm volatile(SAVE_CONTEXT                                         \
-            "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
-            "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
-            "call __switch_to\n\t"                                       \
-            "movq "__percpu_arg([current_task])",%%rsi\n\t"              \
-            __switch_canary                                              \
-            "movq %P[thread_info](%%rsi),%%r8\n\t"                       \
-            "movq %%rax,%%rdi\n\t"                                       \
-            "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"                 \
-            "jnz   ret_from_fork\n\t"                                    \
-            RESTORE_CONTEXT                                              \
-            : "=a" (last)                                                \
-              __switch_canary_oparam                                     \
-            : [next] "S" (next), [prev] "D" (prev),                      \
-              [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
-              [ti_flags] "i" (offsetof(struct thread_info, flags)),      \
-              [_tif_fork] "i" (_TIF_FORK),                               \
-              [thread_info] "i" (offsetof(struct task_struct, stack)),   \
-              [current_task] "m" (current_task)                          \
-              __switch_canary_iparam                                     \
-            : "memory", "cc" __EXTRA_CLOBBER)
-#endif
-
-#ifdef __KERNEL__
-
-extern void native_load_gs_index(unsigned);
-
-/*
- * Load a segment. Fall back on loading the zero
- * segment if something goes wrong..
- */
-#define loadsegment(seg, value)                                                \
-do {                                                                   \
-       unsigned short __val = (value);                                 \
-                                                                       \
-       asm volatile("                                          \n"     \
-                    "1:        movl %k0,%%" #seg "             \n"     \
-                                                                       \
-                    ".section .fixup,\"ax\"                    \n"     \
-                    "2:        xorl %k0,%k0                    \n"     \
-                    "          jmp 1b                          \n"     \
-                    ".previous                                 \n"     \
-                                                                       \
-                    _ASM_EXTABLE(1b, 2b)                               \
-                                                                       \
-                    : "+r" (__val) : : "memory");                      \
-} while (0)
-
-/*
- * Save a segment register away
- */
-#define savesegment(seg, value)                                \
-       asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
-
-/*
- * x86_32 user gs accessors.
- */
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_X86_32_LAZY_GS
-#define get_user_gs(regs)      (u16)({unsigned long v; savesegment(gs, v); v;})
-#define set_user_gs(regs, v)   loadsegment(gs, (unsigned long)(v))
-#define task_user_gs(tsk)      ((tsk)->thread.gs)
-#define lazy_save_gs(v)                savesegment(gs, (v))
-#define lazy_load_gs(v)                loadsegment(gs, (v))
-#else  /* X86_32_LAZY_GS */
-#define get_user_gs(regs)      (u16)((regs)->gs)
-#define set_user_gs(regs, v)   do { (regs)->gs = (v); } while (0)
-#define task_user_gs(tsk)      (task_pt_regs(tsk)->gs)
-#define lazy_save_gs(v)                do { } while (0)
-#define lazy_load_gs(v)                do { } while (0)
-#endif /* X86_32_LAZY_GS */
-#endif /* X86_32 */
-
-static inline unsigned long get_limit(unsigned long segment)
-{
-       unsigned long __limit;
-       asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
-       return __limit + 1;
-}
-
-static inline void native_clts(void)
-{
-       asm volatile("clts");
-}
-
-/*
- * Volatile isn't enough to prevent the compiler from reordering the
- * read/write functions for the control registers and messing everything up.
- * A memory clobber would solve the problem, but would prevent reordering of
- * all loads stores around it, which can hurt performance. Solution is to
- * use a variable and mimic reads and writes to it to enforce serialization
- */
-static unsigned long __force_order;
-
-static inline unsigned long native_read_cr0(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline void native_write_cr0(unsigned long val)
-{
-       asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
-}
-
-static inline unsigned long native_read_cr2(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline void native_write_cr2(unsigned long val)
-{
-       asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
-}
-
-static inline unsigned long native_read_cr3(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline void native_write_cr3(unsigned long val)
-{
-       asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
-}
-
-static inline unsigned long native_read_cr4(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline unsigned long native_read_cr4_safe(void)
-{
-       unsigned long val;
-       /* This could fault if %cr4 does not exist. In x86_64, a cr4 always
-        * exists, so it will never fail. */
-#ifdef CONFIG_X86_32
-       asm volatile("1: mov %%cr4, %0\n"
-                    "2:\n"
-                    _ASM_EXTABLE(1b, 2b)
-                    : "=r" (val), "=m" (__force_order) : "0" (0));
-#else
-       val = native_read_cr4();
-#endif
-       return val;
-}
-
-static inline void native_write_cr4(unsigned long val)
-{
-       asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
-}
-
-#ifdef CONFIG_X86_64
-static inline unsigned long native_read_cr8(void)
-{
-       unsigned long cr8;
-       asm volatile("movq %%cr8,%0" : "=r" (cr8));
-       return cr8;
-}
-
-static inline void native_write_cr8(unsigned long val)
-{
-       asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
-}
-#endif
-
-static inline void native_wbinvd(void)
-{
-       asm volatile("wbinvd": : :"memory");
-}
-
-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-
-static inline unsigned long read_cr0(void)
-{
-       return native_read_cr0();
-}
-
-static inline void write_cr0(unsigned long x)
-{
-       native_write_cr0(x);
-}
-
-static inline unsigned long read_cr2(void)
-{
-       return native_read_cr2();
-}
-
-static inline void write_cr2(unsigned long x)
-{
-       native_write_cr2(x);
-}
-
-static inline unsigned long read_cr3(void)
-{
-       return native_read_cr3();
-}
-
-static inline void write_cr3(unsigned long x)
-{
-       native_write_cr3(x);
-}
-
-static inline unsigned long read_cr4(void)
-{
-       return native_read_cr4();
-}
-
-static inline unsigned long read_cr4_safe(void)
-{
-       return native_read_cr4_safe();
-}
-
-static inline void write_cr4(unsigned long x)
-{
-       native_write_cr4(x);
-}
-
-static inline void wbinvd(void)
-{
-       native_wbinvd();
-}
-
-#ifdef CONFIG_X86_64
-
-static inline unsigned long read_cr8(void)
-{
-       return native_read_cr8();
-}
-
-static inline void write_cr8(unsigned long x)
-{
-       native_write_cr8(x);
-}
-
-static inline void load_gs_index(unsigned selector)
-{
-       native_load_gs_index(selector);
-}
-
-#endif
-
-/* Clear the 'TS' bit */
-static inline void clts(void)
-{
-       native_clts();
-}
-
-#endif/* CONFIG_PARAVIRT */
-
-#define stts() write_cr0(read_cr0() | X86_CR0_TS)
-
-#endif /* __KERNEL__ */
-
-static inline void clflush(volatile void *__p)
-{
-       asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
-}
-
-#define nop() asm volatile ("nop")
-
-void disable_hlt(void);
-void enable_hlt(void);
-
-void cpu_idle_wait(void);
-
-extern unsigned long arch_align_stack(unsigned long sp);
-extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
-
-void default_idle(void);
-bool set_pm_idle_to_default(void);
-
-void stop_this_cpu(void *dummy);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb()   asm volatile("mfence":::"memory")
-#define rmb()  asm volatile("lfence":::"memory")
-#define wmb()  asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     b = 2;
- *     memory_barrier();
- *     p = &b;                         q = p;
- *                                     read_barrier_depends();
- *                                     d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     a = 2;
- *     memory_barrier();
- *     b = 3;                          y = b;
- *                                     read_barrier_depends();
- *                                     x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()     rmb()
-#else
-# define smp_rmb()     barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb()     wmb()
-#else
-# define smp_wmb()     barrier()
-#endif
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static __always_inline void rdtsc_barrier(void)
-{
-       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-/*
- * We handle most unaligned accesses in hardware.  On the other hand
- * unaligned DMA can be quite expensive on some Nehalem processors.
- *
- * Based on this we disable the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN   0
-#endif /* _ASM_X86_SYSTEM_H */
index cfd8144d552742bcd12ac1b42f0d7b45adc5c2fb..ad6df8ccd715881910f4bb80bc23173c8d754630 100644 (file)
@@ -86,7 +86,7 @@ struct thread_info {
 #define TIF_MCE_NOTIFY         10      /* notify userspace of an MCE */
 #define TIF_USER_RETURN_NOTIFY 11      /* notify kernel of userspace return */
 #define TIF_NOTSC              16      /* TSC is not accessible in userland */
-#define TIF_IA32               17      /* 32bit process */
+#define TIF_IA32               17      /* IA32 compatibility process */
 #define TIF_FORK               18      /* ret_from_fork */
 #define TIF_MEMDIE             20      /* is terminating due to OOM killer */
 #define TIF_DEBUG              21      /* uses debug registers */
@@ -95,6 +95,8 @@ struct thread_info {
 #define TIF_BLOCKSTEP          25      /* set when we want DEBUGCTLMSR_BTF */
 #define TIF_LAZY_MMU_UPDATES   27      /* task is updating the mmu lazily */
 #define TIF_SYSCALL_TRACEPOINT 28      /* syscall tracepoint instrumentation */
+#define TIF_ADDR32             29      /* 32-bit address space on 64 bits */
+#define TIF_X32                        30      /* 32-bit native x86-64 binary */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
@@ -116,6 +118,8 @@ struct thread_info {
 #define _TIF_BLOCKSTEP         (1 << TIF_BLOCKSTEP)
 #define _TIF_LAZY_MMU_UPDATES  (1 << TIF_LAZY_MMU_UPDATES)
 #define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
+#define _TIF_ADDR32            (1 << TIF_ADDR32)
+#define _TIF_X32               (1 << TIF_X32)
 
 /* work to do in syscall_trace_enter() */
 #define _TIF_WORK_SYSCALL_ENTRY        \
@@ -262,6 +266,18 @@ static inline void set_restore_sigmask(void)
        ti->status |= TS_RESTORE_SIGMASK;
        set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
 }
+
+static inline bool is_ia32_task(void)
+{
+#ifdef CONFIG_X86_32
+       return true;
+#endif
+#ifdef CONFIG_IA32_EMULATION
+       if (current_thread_info()->status & TS_COMPAT)
+               return true;
+#endif
+       return false;
+}
 #endif /* !__ASSEMBLY__ */
 
 #ifndef __ASSEMBLY__
index 169be8938b96778e76be9541bf37d2e9b8135833..c0e108e08079e9a80ee075a5de44b31b4ba78d97 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/sched.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
+#include <asm/special_insns.h>
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
index 0012d0902c5f1c38dca380413b1f79becb9ad204..88eae2aec619e10951191ccad2c1fd40146f5690 100644 (file)
@@ -89,4 +89,29 @@ asmlinkage void smp_thermal_interrupt(void);
 asmlinkage void mce_threshold_interrupt(void);
 #endif
 
+/* Interrupts/Exceptions */
+enum {
+       X86_TRAP_DE = 0,        /*  0, Divide-by-zero */
+       X86_TRAP_DB,            /*  1, Debug */
+       X86_TRAP_NMI,           /*  2, Non-maskable Interrupt */
+       X86_TRAP_BP,            /*  3, Breakpoint */
+       X86_TRAP_OF,            /*  4, Overflow */
+       X86_TRAP_BR,            /*  5, Bound Range Exceeded */
+       X86_TRAP_UD,            /*  6, Invalid Opcode */
+       X86_TRAP_NM,            /*  7, Device Not Available */
+       X86_TRAP_DF,            /*  8, Double Fault */
+       X86_TRAP_OLD_MF,        /*  9, Coprocessor Segment Overrun */
+       X86_TRAP_TS,            /* 10, Invalid TSS */
+       X86_TRAP_NP,            /* 11, Segment Not Present */
+       X86_TRAP_SS,            /* 12, Stack Segment Fault */
+       X86_TRAP_GP,            /* 13, General Protection Fault */
+       X86_TRAP_PF,            /* 14, Page Fault */
+       X86_TRAP_SPURIOUS,      /* 15, Spurious Interrupt */
+       X86_TRAP_MF,            /* 16, x87 Floating-Point Exception */
+       X86_TRAP_AC,            /* 17, Alignment Check */
+       X86_TRAP_MC,            /* 18, Machine Check */
+       X86_TRAP_XF,            /* 19, SIMD Floating-Point Exception */
+       X86_TRAP_IRET = 32,     /* 32, IRET Exception */
+};
+
 #endif /* _ASM_X86_TRAPS_H */
index 15d99153a96d31a52a72dd69a4f73ddd93373fc8..c91e8b9d588b14d0f86b4ea7a82b5d07c8387c2c 100644 (file)
@@ -61,7 +61,7 @@ extern void check_tsc_sync_source(int cpu);
 extern void check_tsc_sync_target(void);
 
 extern int notsc_setup(char *);
-extern void save_sched_clock_state(void);
-extern void restore_sched_clock_state(void);
+extern void tsc_save_sched_clock_state(void);
+extern void tsc_restore_sched_clock_state(void);
 
 #endif /* _ASM_X86_TSC_H */
index 21f77b89e47a6aeea5ab00c01c28db2d54f0520b..37cdc9d99bb18097c5cde1895606864510de3f5f 100644 (file)
@@ -1,7 +1,17 @@
 #ifndef _ASM_X86_UNISTD_H
 #define _ASM_X86_UNISTD_H 1
 
+/* x32 syscall flag bit */
+#define __X32_SYSCALL_BIT      0x40000000
+
 #ifdef __KERNEL__
+
+# ifdef CONFIG_X86_X32_ABI
+#  define __SYSCALL_MASK (~(__X32_SYSCALL_BIT))
+# else
+#  define __SYSCALL_MASK (~0)
+# endif
+
 # ifdef CONFIG_X86_32
 
 #  include <asm/unistd_32.h>
@@ -14,6 +24,7 @@
 # else
 
 #  include <asm/unistd_64.h>
+#  include <asm/unistd_64_x32.h>
 #  define __ARCH_WANT_COMPAT_SYS_TIME
 
 # endif
 #else
 # ifdef __i386__
 #  include <asm/unistd_32.h>
-# else
+# elif defined(__LP64__)
 #  include <asm/unistd_64.h>
+# else
+#  include <asm/unistd_x32.h>
 # endif
 #endif
 
index 815285bcaceb44b1b6646dc3d1e0760abd445a0e..8b38be2de9e15a7cf149b3c088aac074f1be0463 100644 (file)
@@ -5,13 +5,8 @@
 #include <linux/clocksource.h>
 
 struct vsyscall_gtod_data {
-       seqlock_t       lock;
+       seqcount_t      seq;
 
-       /* open coded 'struct timespec' */
-       time_t          wall_time_sec;
-       u32             wall_time_nsec;
-
-       struct timezone sys_tz;
        struct { /* extract of a clocksource struct */
                int vclock_mode;
                cycle_t cycle_last;
@@ -19,8 +14,16 @@ struct vsyscall_gtod_data {
                u32     mult;
                u32     shift;
        } clock;
-       struct timespec wall_to_monotonic;
+
+       /* open coded 'struct timespec' */
+       time_t          wall_time_sec;
+       u32             wall_time_nsec;
+       u32             monotonic_time_nsec;
+       time_t          monotonic_time_sec;
+
+       struct timezone sys_tz;
        struct timespec wall_time_coarse;
+       struct timespec monotonic_time_coarse;
 };
 extern struct vsyscall_gtod_data vsyscall_gtod_data;
 
index e0f9aa16358bc157c71f1a31ccc5969d96b23584..5da71c27cc59e47485bcdee1bcce343d1118adf9 100644 (file)
@@ -16,7 +16,6 @@
 #define _ASM_X86_VIRTEX_H
 
 #include <asm/processor.h>
-#include <asm/system.h>
 
 #include <asm/vmx.h>
 #include <asm/svm.h>
index 6bf5b8e478c067f9058bb6bb17a383065d31204b..92e54abf89e0bc31aae93b298ae5d42b7994fef7 100644 (file)
@@ -18,6 +18,11 @@ static const struct cpumask *x2apic_target_cpus(void)
        return cpu_online_mask;
 }
 
+static int x2apic_apic_id_valid(int apicid)
+{
+       return 1;
+}
+
 static int x2apic_apic_id_registered(void)
 {
        return 1;
index 517d4767ffdda95e249cc5c173eb008a439cd346..baaca8defec8032463d1a87d53137a8c88f63639 100644 (file)
@@ -145,9 +145,11 @@ struct x86_init_ops {
 /**
  * struct x86_cpuinit_ops - platform specific cpu hotplug setups
  * @setup_percpu_clockev:      set up the per cpu clock event device
+ * @early_percpu_clock_init:   early init of the per cpu clock event device
  */
 struct x86_cpuinit_ops {
        void (*setup_percpu_clockev)(void);
+       void (*early_percpu_clock_init)(void);
        void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);
 };
 
@@ -160,6 +162,8 @@ struct x86_cpuinit_ops {
  * @is_untracked_pat_range     exclude from PAT logic
  * @nmi_init                   enable NMI on cpus
  * @i8042_detect               pre-detect if i8042 controller exists
+ * @save_sched_clock_state:    save state for sched_clock() on suspend
+ * @restore_sched_clock_state: restore state for sched_clock() on resume
  */
 struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
@@ -171,6 +175,8 @@ struct x86_platform_ops {
        void (*nmi_init)(void);
        unsigned char (*get_nmi_reason)(void);
        int (*i8042_detect)(void);
+       void (*save_sched_clock_state)(void);
+       void (*restore_sched_clock_state)(void);
 };
 
 struct pci_dev;
index 406ed77216d02c586963b8633c14d5ed715816a6..0f42c2f44311a9332ec538e32d09cd34cb67c396 100644 (file)
@@ -239,7 +239,7 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
         * to not preallocating memory for all NR_CPUS
         * when we use CPU hotplug.
         */
-       if (!cpu_has_x2apic && (apic_id >= 0xff) && enabled)
+       if (!apic->apic_id_valid(apic_id) && enabled)
                printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
        else
                acpi_register_lapic(apic_id, enabled);
index f50e7fb2a201b752c5c007dc9da41397ca9c6c46..d2b7f27781bce0a559580d0596980b66a8865920 100644 (file)
@@ -14,6 +14,7 @@
 #include <acpi/processor.h>
 #include <asm/acpi.h>
 #include <asm/mwait.h>
+#include <asm/special_insns.h>
 
 /*
  * Initialize bm_flags based on the CPU cache properties
index 2eec05b6d1b822c74032b9356f20abc060f822ec..11544d8f1e975e30c1e3c0d9aafa58b4ba67a1da 100644 (file)
@@ -383,20 +383,25 @@ static inline int eilvt_entry_is_changeable(unsigned int old, unsigned int new)
 
 static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
 {
-       unsigned int rsvd;                      /* 0: uninitialized */
+       unsigned int rsvd, vector;
 
        if (offset >= APIC_EILVT_NR_MAX)
                return ~0;
 
-       rsvd = atomic_read(&eilvt_offsets[offset]) & ~APIC_EILVT_MASKED;
+       rsvd = atomic_read(&eilvt_offsets[offset]);
        do {
-               if (rsvd &&
-                   !eilvt_entry_is_changeable(rsvd, new))
+               vector = rsvd & ~APIC_EILVT_MASKED;     /* 0: unassigned */
+               if (vector && !eilvt_entry_is_changeable(vector, new))
                        /* may not change if vectors are different */
                        return rsvd;
                rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
        } while (rsvd != new);
 
+       rsvd &= ~APIC_EILVT_MASKED;
+       if (rsvd && rsvd != vector)
+               pr_info("LVT offset %d assigned for vector 0x%02x\n",
+                       offset, rsvd);
+
        return new;
 }
 
index d9ea5f331ac5930d02dfb8c48905c468aa0330fc..899803e032142662650389d693ca4594a08ab18d 100644 (file)
@@ -229,11 +229,10 @@ static int __init numachip_system_init(void)
 }
 early_initcall(numachip_system_init);
 
-static int __cpuinit numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static int numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
        if (!strncmp(oem_id, "NUMASC", 6)) {
                numachip_system = 1;
-               setup_force_cpu_cap(X86_FEATURE_X2APIC);
                return 1;
        }
 
index 6d10a66fc5a9195772be6f6622fb09cd2aadc0a3..e88300d8e80aa2465aec91af3768578dee32c727 100644 (file)
 #include <asm/apic.h>
 
 #define __apicdebuginit(type) static type __init
+
 #define for_each_irq_pin(entry, head) \
        for (entry = head; entry; entry = entry->next)
 
+static void            __init __ioapic_init_mappings(void);
+
+static unsigned int    __io_apic_read  (unsigned int apic, unsigned int reg);
+static void            __io_apic_write (unsigned int apic, unsigned int reg, unsigned int val);
+static void            __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
+
+static struct io_apic_ops io_apic_ops = {
+       .init   = __ioapic_init_mappings,
+       .read   = __io_apic_read,
+       .write  = __io_apic_write,
+       .modify = __io_apic_modify,
+};
+
+void __init set_io_apic_ops(const struct io_apic_ops *ops)
+{
+       io_apic_ops = *ops;
+}
+
 /*
  *      Is the SiS APIC rmw bug present ?
  *      -1 = don't know, 0 = no, 1 = yes
@@ -294,6 +313,22 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
        irq_free_desc(at);
 }
 
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+       return io_apic_ops.read(apic, reg);
+}
+
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+{
+       io_apic_ops.write(apic, reg, value);
+}
+
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+{
+       io_apic_ops.modify(apic, reg, value);
+}
+
+
 struct io_apic {
        unsigned int index;
        unsigned int unused[3];
@@ -314,16 +349,17 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
        writel(vector, &io_apic->eoi);
 }
 
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+static unsigned int __io_apic_read(unsigned int apic, unsigned int reg)
 {
        struct io_apic __iomem *io_apic = io_apic_base(apic);
        writel(reg, &io_apic->index);
        return readl(&io_apic->data);
 }
 
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
 {
        struct io_apic __iomem *io_apic = io_apic_base(apic);
+
        writel(reg, &io_apic->index);
        writel(value, &io_apic->data);
 }
@@ -334,7 +370,7 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
  *
  * Older SiS APIC requires we rewrite the index register
  */
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
        struct io_apic __iomem *io_apic = io_apic_base(apic);
 
@@ -377,6 +413,7 @@ static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin)
 
        eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
        eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+
        return eu.entry;
 }
 
@@ -384,9 +421,11 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
 {
        union entry_union eu;
        unsigned long flags;
+
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        eu.entry = __ioapic_read_entry(apic, pin);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+
        return eu.entry;
 }
 
@@ -396,8 +435,7 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
  * the interrupt, and we need to make sure the entry is fully populated
  * before that happens.
  */
-static void
-__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+static void __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 {
        union entry_union eu = {{0, 0}};
 
@@ -409,6 +447,7 @@ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 {
        unsigned long flags;
+
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        __ioapic_write_entry(apic, pin, e);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
@@ -435,8 +474,7 @@ static void ioapic_mask_entry(int apic, int pin)
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static int
-__add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
+static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
 {
        struct irq_pin_list **last, *entry;
 
@@ -521,6 +559,7 @@ static void io_apic_sync(struct irq_pin_list *entry)
         * a dummy read from the IO-APIC
         */
        struct io_apic __iomem *io_apic;
+
        io_apic = io_apic_base(entry->apic);
        readl(&io_apic->data);
 }
@@ -2512,21 +2551,73 @@ static void ack_apic_edge(struct irq_data *data)
 
 atomic_t irq_mis_count;
 
-static void ack_apic_level(struct irq_data *data)
-{
-       struct irq_cfg *cfg = data->chip_data;
-       int i, do_unmask_irq = 0, irq = data->irq;
-       unsigned long v;
-
-       irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
+static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)
+{
        /* If we are moving the irq we need to mask it */
        if (unlikely(irqd_is_setaffinity_pending(data))) {
-               do_unmask_irq = 1;
                mask_ioapic(cfg);
+               return true;
        }
+       return false;
+}
+
+static inline void ioapic_irqd_unmask(struct irq_data *data,
+                                     struct irq_cfg *cfg, bool masked)
+{
+       if (unlikely(masked)) {
+               /* Only migrate the irq if the ack has been received.
+                *
+                * On rare occasions the broadcast level triggered ack gets
+                * delayed going to ioapics, and if we reprogram the
+                * vector while Remote IRR is still set the irq will never
+                * fire again.
+                *
+                * To prevent this scenario we read the Remote IRR bit
+                * of the ioapic.  This has two effects.
+                * - On any sane system the read of the ioapic will
+                *   flush writes (and acks) going to the ioapic from
+                *   this cpu.
+                * - We get to see if the ACK has actually been delivered.
+                *
+                * Based on failed experiments of reprogramming the
+                * ioapic entry from outside of irq context starting
+                * with masking the ioapic entry and then polling until
+                * Remote IRR was clear before reprogramming the
+                * ioapic I don't trust the Remote IRR bit to be
+                * completey accurate.
+                *
+                * However there appears to be no other way to plug
+                * this race, so if the Remote IRR bit is not
+                * accurate and is causing problems then it is a hardware bug
+                * and you can go talk to the chipset vendor about it.
+                */
+               if (!io_apic_level_ack_pending(cfg))
+                       irq_move_masked_irq(data);
+               unmask_ioapic(cfg);
+       }
+}
+#else
+static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)
+{
+       return false;
+}
+static inline void ioapic_irqd_unmask(struct irq_data *data,
+                                     struct irq_cfg *cfg, bool masked)
+{
+}
 #endif
 
+static void ack_apic_level(struct irq_data *data)
+{
+       struct irq_cfg *cfg = data->chip_data;
+       int i, irq = data->irq;
+       unsigned long v;
+       bool masked;
+
+       irq_complete_move(cfg);
+       masked = ioapic_irqd_mask(data, cfg);
+
        /*
         * It appears there is an erratum which affects at least version 0x11
         * of I/O APIC (that's the 82093AA and cores integrated into various
@@ -2581,38 +2672,7 @@ static void ack_apic_level(struct irq_data *data)
                eoi_ioapic_irq(irq, cfg);
        }
 
-       /* Now we can move and renable the irq */
-       if (unlikely(do_unmask_irq)) {
-               /* Only migrate the irq if the ack has been received.
-                *
-                * On rare occasions the broadcast level triggered ack gets
-                * delayed going to ioapics, and if we reprogram the
-                * vector while Remote IRR is still set the irq will never
-                * fire again.
-                *
-                * To prevent this scenario we read the Remote IRR bit
-                * of the ioapic.  This has two effects.
-                * - On any sane system the read of the ioapic will
-                *   flush writes (and acks) going to the ioapic from
-                *   this cpu.
-                * - We get to see if the ACK has actually been delivered.
-                *
-                * Based on failed experiments of reprogramming the
-                * ioapic entry from outside of irq context starting
-                * with masking the ioapic entry and then polling until
-                * Remote IRR was clear before reprogramming the
-                * ioapic I don't trust the Remote IRR bit to be
-                * completey accurate.
-                *
-                * However there appears to be no other way to plug
-                * this race, so if the Remote IRR bit is not
-                * accurate and is causing problems then it is a hardware bug
-                * and you can go talk to the chipset vendor about it.
-                */
-               if (!io_apic_level_ack_pending(cfg))
-                       irq_move_masked_irq(data);
-               unmask_ioapic(cfg);
-       }
+       ioapic_irqd_unmask(data, cfg, masked);
 }
 
 #ifdef CONFIG_IRQ_REMAP
@@ -3872,6 +3932,11 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
 }
 
 void __init ioapic_and_gsi_init(void)
+{
+       io_apic_ops.init();
+}
+
+static void __init __ioapic_init_mappings(void)
 {
        unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
        struct resource *ioapic_res;
index 9193713060a921bcf820a8cd6fedb84d77be7664..48f3103b3c93f42cf885127ee682d4fbbae563b6 100644 (file)
@@ -213,7 +213,7 @@ static struct apic apic_x2apic_cluster = {
        .name                           = "cluster x2apic",
        .probe                          = x2apic_cluster_probe,
        .acpi_madt_oem_check            = x2apic_acpi_madt_oem_check,
-       .apic_id_valid                  = default_apic_id_valid,
+       .apic_id_valid                  = x2apic_apic_id_valid,
        .apic_id_registered             = x2apic_apic_id_registered,
 
        .irq_delivery_mode              = dest_LowestPrio,
index bcd1db6eaca9a6a4aeb5b44f6b0f7a566d985dae..8a778db45e3a508ef2402596ee57884eaf639166 100644 (file)
@@ -119,7 +119,7 @@ static struct apic apic_x2apic_phys = {
        .name                           = "physical x2apic",
        .probe                          = x2apic_phys_probe,
        .acpi_madt_oem_check            = x2apic_acpi_madt_oem_check,
-       .apic_id_valid                  = default_apic_id_valid,
+       .apic_id_valid                  = x2apic_apic_id_valid,
        .apic_id_registered             = x2apic_apic_id_registered,
 
        .irq_delivery_mode              = dest_Fixed,
index fc47714258524ddce82163eaf11aef32189a6f84..87bfa69e216e60612d929527c0358b9b91432f52 100644 (file)
@@ -266,6 +266,11 @@ static void uv_send_IPI_all(int vector)
        uv_send_IPI_mask(cpu_online_mask, vector);
 }
 
+static int uv_apic_id_valid(int apicid)
+{
+       return 1;
+}
+
 static int uv_apic_id_registered(void)
 {
        return 1;
@@ -351,7 +356,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
        .name                           = "UV large system",
        .probe                          = uv_probe,
        .acpi_madt_oem_check            = uv_acpi_madt_oem_check,
-       .apic_id_valid                  = default_apic_id_valid,
+       .apic_id_valid                  = uv_apic_id_valid,
        .apic_id_registered             = uv_apic_id_registered,
 
        .irq_delivery_mode              = dest_Fixed,
index 5d56931a15b352b70262968db9b94a7ab3ac9ea6..459e78cbf61e1dd3778a2c09258b965b46fdd9bd 100644 (file)
 #include <linux/syscore_ops.h>
 #include <linux/i8253.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/olpc.h>
index 834e897b1e25b66e864d010266e5df29fecfb892..1b4754f82ba7cb8bc1c0b4b1a8b109c1d742c2f8 100644 (file)
@@ -1,6 +1,12 @@
 #include <asm/ia32.h>
 
 #define __SYSCALL_64(nr, sym, compat) [nr] = 1,
+#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1,
+#ifdef CONFIG_X86_X32_ABI
+# define __SYSCALL_X32(nr, sym, compat) [nr] = 1,
+#else
+# define __SYSCALL_X32(nr, sym, compat) /* nothing */
+#endif
 static char syscalls_64[] = {
 #include <asm/syscalls_64.h>
 };
index e49477444fff54ea2d7d0698217962d09f545387..67e258362a3d56d7f94c675ec876705003469c3a 100644 (file)
@@ -999,7 +999,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
        else
                printk(KERN_CONT "\n");
 
-       __print_cpu_msr();
+       print_cpu_msr(c);
 }
 
 void __cpuinit print_cpu_msr(struct cpuinfo_x86 *c)
index 5c0e6533d9bcdcc18bf43ddeab16ba43cefed1d9..2d5454cd2c4fdef4d775fdf7210c4f4885a77710 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/smp.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
index 67bb17a37a0afffb9ddee5f8ebad08d1c931c153..47a1870279aadc5607171737c0df7c3f54d2b25f 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/cpu.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/idle.h>
 #include <asm/mce.h>
index 54060f565974e7e9ae844b66734f388bf4692baa..2d7998fb628cb5679069b5ef50ba7d6e41a1c498 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/init.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
index 97b26356e9ee8b022b45ae1adc5ef7628a5e2539..75772ae6c65f81cbc2268120b1fdcf3bad80028f 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/processor-flags.h>
 #include <asm/cpufeature.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 #include <asm/pat.h>
index 79289632cb270cb4aa02c1e5cc58d4c3de5b53b1..a041e094b8b9fd68a520d5952c8ed05a4bdd7380 100644 (file)
@@ -167,6 +167,7 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
 {
        int err = 0;
        mtrr_type type;
+       unsigned long base;
        unsigned long size;
        struct mtrr_sentry sentry;
        struct mtrr_gentry gentry;
@@ -267,14 +268,14 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
 #endif
                if (gentry.regnum >= num_var_ranges)
                        return -EINVAL;
-               mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
+               mtrr_if->get(gentry.regnum, &base, &size, &type);
 
                /* Hide entries that go above 4GB */
-               if (gentry.base + size - 1 >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT))
+               if (base + size - 1 >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT))
                    || size >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT)))
                        gentry.base = gentry.size = gentry.type = 0;
                else {
-                       gentry.base <<= PAGE_SHIFT;
+                       gentry.base = base << PAGE_SHIFT;
                        gentry.size = size << PAGE_SHIFT;
                        gentry.type = type;
                }
@@ -321,11 +322,12 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
 #endif
                if (gentry.regnum >= num_var_ranges)
                        return -EINVAL;
-               mtrr_if->get(gentry.regnum, &gentry.base, &size, &type);
+               mtrr_if->get(gentry.regnum, &base, &size, &type);
                /* Hide entries that would overflow */
                if (size != (__typeof__(gentry.size))size)
                        gentry.base = gentry.size = gentry.type = 0;
                else {
+                       gentry.base = base;
                        gentry.size = size;
                        gentry.type = type;
                }
index fa2900c0e3984debf8370b3fc72cdf8a295d34b9..40883ffe2da9261b4f34c2997d2b5e533df25648 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/apic.h>
 #include <asm/stacktrace.h>
 #include <asm/nmi.h>
-#include <asm/compat.h>
 #include <asm/smp.h>
 #include <asm/alternative.h>
 #include <asm/timer.h>
@@ -1748,6 +1747,9 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 }
 
 #ifdef CONFIG_COMPAT
+
+#include <asm/compat.h>
+
 static inline int
 perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
 {
index a524353d93f21181e5998b592e7c39072ad1f182..39472dd2323f31b030ed3d782b297794f8502b1b 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/processor.h>
 #include <asm/msr.h>
-#include <asm/system.h>
 
 static struct class *cpuid_class;
 
index 4025fe4f928f6f4cb2ddcfc0233197e9e0b3ad44..1b81839b6c8890f261e486429db51f37a9c68042 100644 (file)
@@ -37,13 +37,16 @@ print_ftrace_graph_addr(unsigned long addr, void *data,
                        const struct stacktrace_ops *ops,
                        struct thread_info *tinfo, int *graph)
 {
-       struct task_struct *task = tinfo->task;
+       struct task_struct *task;
        unsigned long ret_addr;
-       int index = task->curr_ret_stack;
+       int index;
 
        if (addr != (unsigned long)return_to_handler)
                return;
 
+       task = tinfo->task;
+       index = task->curr_ret_stack;
+
        if (!task->ret_stack || index < *graph)
                return;
 
@@ -265,7 +268,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
 #endif
        printk("\n");
        if (notify_die(DIE_OOPS, str, regs, err,
-                       current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+                       current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
                return 1;
 
        show_registers(regs);
index 734ebd1d3caabf0e0b058a1f8ed6aa947c1caf95..cdc79b5cfcd925c014010a3fe60723a14143616a 100644 (file)
@@ -481,7 +481,12 @@ GLOBAL(system_call_after_swapgs)
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jnz tracesys
 system_call_fastpath:
+#if __SYSCALL_MASK == ~0
        cmpq $__NR_syscall_max,%rax
+#else
+       andl $__SYSCALL_MASK,%eax
+       cmpl $__NR_syscall_max,%eax
+#endif
        ja badsys
        movq %r10,%rcx
        call *sys_call_table(,%rax,8)  # XXX:    rip relative
@@ -595,7 +600,12 @@ tracesys:
         */
        LOAD_ARGS ARGOFFSET, 1
        RESTORE_REST
+#if __SYSCALL_MASK == ~0
        cmpq $__NR_syscall_max,%rax
+#else
+       andl $__SYSCALL_MASK,%eax
+       cmpl $__NR_syscall_max,%eax
+#endif
        ja   int_ret_from_sys_call      /* RAX(%rsp) set to -ENOSYS above */
        movq %r10,%rcx  /* fixup for C */
        call *sys_call_table(,%rax,8)
@@ -735,6 +745,40 @@ ENTRY(stub_rt_sigreturn)
        CFI_ENDPROC
 END(stub_rt_sigreturn)
 
+#ifdef CONFIG_X86_X32_ABI
+       PTREGSCALL stub_x32_sigaltstack, sys32_sigaltstack, %rdx
+
+ENTRY(stub_x32_rt_sigreturn)
+       CFI_STARTPROC
+       addq $8, %rsp
+       PARTIAL_FRAME 0
+       SAVE_REST
+       movq %rsp,%rdi
+       FIXUP_TOP_OF_STACK %r11
+       call sys32_x32_rt_sigreturn
+       movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
+       RESTORE_REST
+       jmp int_ret_from_sys_call
+       CFI_ENDPROC
+END(stub_x32_rt_sigreturn)
+
+ENTRY(stub_x32_execve)
+       CFI_STARTPROC
+       addq $8, %rsp
+       PARTIAL_FRAME 0
+       SAVE_REST
+       FIXUP_TOP_OF_STACK %r11
+       movq %rsp, %rcx
+       call sys32_execve
+       RESTORE_TOP_OF_STACK %r11
+       movq %rax,RAX(%rsp)
+       RESTORE_REST
+       jmp int_ret_from_sys_call
+       CFI_ENDPROC
+END(stub_x32_execve)
+
+#endif
+
 /*
  * Build the entry stubs and pointer table with some assembler magic.
  * We pack 7 stubs into a single 32-byte chunk, which will fit in a
index 610485223bdb8fd48ff71fb4ae5711b711c62361..36d1853e91af58c0ee2b9ee8df2c045229f22936 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
index 43e2b1cff0a7f5963fa585818a883d5ffec28e2b..252981afd6c4063cabaf3ebb0145af1f620f8209 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
@@ -61,7 +60,7 @@ static irqreturn_t math_error_irq(int cpl, void *dev_id)
        outb(0, 0xF0);
        if (ignore_fpu_irq || !boot_cpu_data.hard_math)
                return IRQ_NONE;
-       math_error(get_irq_regs(), 0, 16);
+       math_error(get_irq_regs(), 0, X86_TRAP_MF);
        return IRQ_HANDLED;
 }
 
index fdc37b3d0ce35ab379b09eed4d2811fdf95fc511..db6720edfdd04f6d6a5e57da090c36db7a28eb31 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <asm/debugreg.h>
 #include <asm/apicdef.h>
-#include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/nmi.h>
 
index 44842d756b29fa9b2705fb8c57189fe5d28b5732..f8492da65bfcb03e2775638ad5ce9502099d62c8 100644 (file)
@@ -136,6 +136,15 @@ int kvm_register_clock(char *txt)
        return ret;
 }
 
+static void kvm_save_sched_clock_state(void)
+{
+}
+
+static void kvm_restore_sched_clock_state(void)
+{
+       kvm_register_clock("primary cpu clock, resume");
+}
+
 #ifdef CONFIG_X86_LOCAL_APIC
 static void __cpuinit kvm_setup_secondary_clock(void)
 {
@@ -144,8 +153,6 @@ static void __cpuinit kvm_setup_secondary_clock(void)
         * we shouldn't fail.
         */
        WARN_ON(kvm_register_clock("secondary cpu clock"));
-       /* ok, done with our trickery, call native */
-       setup_secondary_APIC_clock();
 }
 #endif
 
@@ -194,9 +201,11 @@ void __init kvmclock_init(void)
        x86_platform.get_wallclock = kvm_get_wallclock;
        x86_platform.set_wallclock = kvm_set_wallclock;
 #ifdef CONFIG_X86_LOCAL_APIC
-       x86_cpuinit.setup_percpu_clockev =
+       x86_cpuinit.early_percpu_clock_init =
                kvm_setup_secondary_clock;
 #endif
+       x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
+       x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
        machine_ops.shutdown  = kvm_shutdown;
 #ifdef CONFIG_KEXEC
        machine_ops.crash_shutdown  = kvm_crash_shutdown;
index ea697263b3738d2b20ef1131cb28ff8be44aa021..ebc9873989233dcba13d1fa1af14e3e921959a85 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
 #include <asm/mmu_context.h>
index a3fa43ba5d3b941892164b794825fcbb423d90ef..5b19e4d78b008537ece6591cbb11fb3bf5fc57bd 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/apic.h>
 #include <asm/cpufeature.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/debugreg.h>
 
index 177183cbb6ae344549df033db105f508da295887..7eb1e2b9782769378d56930a73fb6e9410d62da0 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/mca.h>
 #include <linux/kprobes.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/proc_fs.h>
 #include <linux/mman.h>
index 925179f871decdc55cefe1bb3b3a9b6d99c67335..f21fd94ac89700b912ce5392c1bc7381ced99601 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/gfp.h>
 #include <linux/jump_label.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
index 96356762a51dfd0f700eb4eb45a33d2bbcd32aa0..eb113693f04320e927a6a2856124b97d70d4f6ce 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <asm/processor.h>
 #include <asm/msr.h>
-#include <asm/system.h>
 
 static struct class *msr_class;
 
index 9c57c02e54f6f7ee8216b3a6db0e832780570a8a..ab137605e694d81ae9adae2d9483d8024936cd2d 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/apic.h>
 #include <asm/tlbflush.h>
 #include <asm/timer.h>
+#include <asm/special_insns.h>
 
 /* nop stub */
 void _paravirt_nop(void)
index 726494b5834584d85ccc461f8a8ac04d283c1e31..6ac5782f4d6bf6cfb90666bc5288aad548d0c04f 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/calgary.h>
 #include <asm/tce.h>
 #include <asm/pci-direct.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/rio.h>
 #include <asm/bios_ebda.h>
index 14baf78d5a1fd86b969941550f83024ed7c77246..a33afaa5ddb78e2594f706b826fee37a9dd02129 100644 (file)
 #include <linux/user-return-notifier.h>
 #include <linux/dmi.h>
 #include <linux/utsname.h>
+#include <linux/stackprotector.h>
+#include <linux/tick.h>
+#include <linux/cpuidle.h>
 #include <trace/events/power.h>
 #include <linux/hw_breakpoint.h>
 #include <asm/cpu.h>
-#include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/syscalls.h>
 #include <asm/idle.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
 #include <asm/debugreg.h>
+#include <asm/nmi.h>
+
+#ifdef CONFIG_X86_64
+static DEFINE_PER_CPU(unsigned char, is_idle);
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+       atomic_notifier_chain_register(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+       atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
+#endif
 
 struct kmem_cache *task_xstate_cachep;
 EXPORT_SYMBOL_GPL(task_xstate_cachep);
@@ -371,6 +391,99 @@ static inline int hlt_use_halt(void)
 }
 #endif
 
+#ifndef CONFIG_SMP
+static inline void play_dead(void)
+{
+       BUG();
+}
+#endif
+
+#ifdef CONFIG_X86_64
+void enter_idle(void)
+{
+       percpu_write(is_idle, 1);
+       atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+}
+
+static void __exit_idle(void)
+{
+       if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
+               return;
+       atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+}
+
+/* Called from interrupts to signify idle end */
+void exit_idle(void)
+{
+       /* idle loop has pid 0 */
+       if (current->pid)
+               return;
+       __exit_idle();
+}
+#endif
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+       /*
+        * If we're the non-boot CPU, nothing set the stack canary up
+        * for us.  CPU0 already has it initialized but no harm in
+        * doing it again.  This is a good place for updating it, as
+        * we wont ever return from this function (so the invalid
+        * canaries already on the stack wont ever trigger).
+        */
+       boot_init_stack_canary();
+       current_thread_info()->status |= TS_POLLING;
+
+       while (1) {
+               tick_nohz_idle_enter();
+
+               while (!need_resched()) {
+                       rmb();
+
+                       if (cpu_is_offline(smp_processor_id()))
+                               play_dead();
+
+                       /*
+                        * Idle routines should keep interrupts disabled
+                        * from here on, until they go to idle.
+                        * Otherwise, idle callbacks can misfire.
+                        */
+                       local_touch_nmi();
+                       local_irq_disable();
+
+                       enter_idle();
+
+                       /* Don't trace irqs off for idle */
+                       stop_critical_timings();
+
+                       /* enter_idle() needs rcu for notifiers */
+                       rcu_idle_enter();
+
+                       if (cpuidle_idle_call())
+                               pm_idle();
+
+                       rcu_idle_exit();
+                       start_critical_timings();
+
+                       /* In many cases the interrupt that ended idle
+                          has already called exit_idle. But some idle
+                          loops can be woken up without interrupt. */
+                       __exit_idle();
+               }
+
+               tick_nohz_idle_exit();
+               preempt_enable_no_resched();
+               schedule();
+               preempt_disable();
+       }
+}
+
 /*
  * We use this if we don't have any better
  * idle routine..
index 9d7d4842bfafee620bbead3aac128594bbe7f912..ae6847303e265c80c2199ab18884ee16e25bf386 100644 (file)
@@ -9,7 +9,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#include <linux/stackprotector.h>
 #include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/personality.h>
-#include <linux/tick.h>
 #include <linux/percpu.h>
 #include <linux/prctl.h>
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/kdebug.h>
-#include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -58,7 +54,7 @@
 #include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
-#include <asm/nmi.h>
+#include <asm/switch_to.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
@@ -70,60 +66,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return ((unsigned long *)tsk->thread.sp)[3];
 }
 
-#ifndef CONFIG_SMP
-static inline void play_dead(void)
-{
-       BUG();
-}
-#endif
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle(void)
-{
-       int cpu = smp_processor_id();
-
-       /*
-        * If we're the non-boot CPU, nothing set the stack canary up
-        * for us.  CPU0 already has it initialized but no harm in
-        * doing it again.  This is a good place for updating it, as
-        * we wont ever return from this function (so the invalid
-        * canaries already on the stack wont ever trigger).
-        */
-       boot_init_stack_canary();
-
-       current_thread_info()->status |= TS_POLLING;
-
-       /* endless idle loop with no priority at all */
-       while (1) {
-               tick_nohz_idle_enter();
-               rcu_idle_enter();
-               while (!need_resched()) {
-
-                       check_pgt_cache();
-                       rmb();
-
-                       if (cpu_is_offline(cpu))
-                               play_dead();
-
-                       local_touch_nmi();
-                       local_irq_disable();
-                       /* Don't trace irqs off for idle */
-                       stop_critical_timings();
-                       if (cpuidle_idle_call())
-                               pm_idle();
-                       start_critical_timings();
-               }
-               rcu_idle_exit();
-               tick_nohz_idle_exit();
-               schedule_preempt_disabled();
-       }
-}
-
 void __show_regs(struct pt_regs *regs, int all)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
index 292da13fc5aa85867522a5004475cfa9c594e56a..733ca39f367ebcc222eaca07b87eb170f2831e1e 100644 (file)
@@ -14,7 +14,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#include <linux/stackprotector.h>
 #include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
-#include <linux/tick.h>
 #include <linux/prctl.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/ftrace.h>
-#include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
 #include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
-#include <asm/nmi.h>
+#include <asm/switch_to.h>
 
 asmlinkage extern void ret_from_fork(void);
 
 DEFINE_PER_CPU(unsigned long, old_rsp);
-static DEFINE_PER_CPU(unsigned char, is_idle);
-
-static ATOMIC_NOTIFIER_HEAD(idle_notifier);
-
-void idle_notifier_register(struct notifier_block *n)
-{
-       atomic_notifier_chain_register(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_register);
-
-void idle_notifier_unregister(struct notifier_block *n)
-{
-       atomic_notifier_chain_unregister(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_unregister);
-
-void enter_idle(void)
-{
-       percpu_write(is_idle, 1);
-       atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
-}
-
-static void __exit_idle(void)
-{
-       if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
-               return;
-       atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
-}
-
-/* Called from interrupts to signify idle end */
-void exit_idle(void)
-{
-       /* idle loop has pid 0 */
-       if (current->pid)
-               return;
-       __exit_idle();
-}
-
-#ifndef CONFIG_SMP
-static inline void play_dead(void)
-{
-       BUG();
-}
-#endif
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle(void)
-{
-       current_thread_info()->status |= TS_POLLING;
-
-       /*
-        * If we're the non-boot CPU, nothing set the stack canary up
-        * for us.  CPU0 already has it initialized but no harm in
-        * doing it again.  This is a good place for updating it, as
-        * we wont ever return from this function (so the invalid
-        * canaries already on the stack wont ever trigger).
-        */
-       boot_init_stack_canary();
-
-       /* endless idle loop with no priority at all */
-       while (1) {
-               tick_nohz_idle_enter();
-               while (!need_resched()) {
-
-                       rmb();
-
-                       if (cpu_is_offline(smp_processor_id()))
-                               play_dead();
-                       /*
-                        * Idle routines should keep interrupts disabled
-                        * from here on, until they go to idle.
-                        * Otherwise, idle callbacks can misfire.
-                        */
-                       local_touch_nmi();
-                       local_irq_disable();
-                       enter_idle();
-                       /* Don't trace irqs off for idle */
-                       stop_critical_timings();
-
-                       /* enter_idle() needs rcu for notifiers */
-                       rcu_idle_enter();
-
-                       if (cpuidle_idle_call())
-                               pm_idle();
-
-                       rcu_idle_exit();
-                       start_critical_timings();
-
-                       /* In many cases the interrupt that ended idle
-                          has already called exit_idle. But some idle
-                          loops can be woken up without interrupt. */
-                       __exit_idle();
-               }
-
-               tick_nohz_idle_exit();
-               schedule_preempt_disabled();
-       }
-}
 
 /* Prints also some state that isn't saved in the pt_regs */
 void __show_regs(struct pt_regs *regs, int all)
@@ -365,7 +258,9 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp)
 {
        start_thread_common(regs, new_ip, new_sp,
-                           __USER32_CS, __USER32_DS, __USER32_DS);
+                           test_thread_flag(TIF_X32)
+                           ? __USER_CS : __USER32_CS,
+                           __USER_DS, __USER_DS);
 }
 #endif
 
@@ -488,6 +383,8 @@ void set_personality_64bit(void)
 
        /* Make sure to be in 64bit mode */
        clear_thread_flag(TIF_IA32);
+       clear_thread_flag(TIF_ADDR32);
+       clear_thread_flag(TIF_X32);
 
        /* Ensure the corresponding mm is not marked. */
        if (current->mm)
@@ -500,20 +397,31 @@ void set_personality_64bit(void)
        current->personality &= ~READ_IMPLIES_EXEC;
 }
 
-void set_personality_ia32(void)
+void set_personality_ia32(bool x32)
 {
        /* inherit personality from parent */
 
        /* Make sure to be in 32bit mode */
-       set_thread_flag(TIF_IA32);
-       current->personality |= force_personality32;
+       set_thread_flag(TIF_ADDR32);
 
        /* Mark the associated mm as containing 32-bit tasks. */
        if (current->mm)
                current->mm->context.ia32_compat = 1;
 
-       /* Prepare the first "return" to user space */
-       current_thread_info()->status |= TS_COMPAT;
+       if (x32) {
+               clear_thread_flag(TIF_IA32);
+               set_thread_flag(TIF_X32);
+               current->personality &= ~READ_IMPLIES_EXEC;
+               /* is_compat_task() uses the presence of the x32
+                  syscall bit flag to determine compat status */
+               current_thread_info()->status &= ~TS_COMPAT;
+       } else {
+               set_thread_flag(TIF_IA32);
+               clear_thread_flag(TIF_X32);
+               current->personality |= force_personality32;
+               /* Prepare the first "return" to user space */
+               current_thread_info()->status |= TS_COMPAT;
+       }
 }
 
 unsigned long get_wchan(struct task_struct *p)
index 78f05e438be5306bac98181623ea4ede8a9d0c94..685845cf16e0963efd746e1d1ec3b49b69278cb6 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
@@ -34,6 +33,7 @@
 #include <asm/prctl.h>
 #include <asm/proto.h>
 #include <asm/hw_breakpoint.h>
+#include <asm/traps.h>
 
 #include "tls.h"
 
@@ -1131,6 +1131,100 @@ static int genregs32_set(struct task_struct *target,
        return ret;
 }
 
+#ifdef CONFIG_X86_X32_ABI
+static long x32_arch_ptrace(struct task_struct *child,
+                           compat_long_t request, compat_ulong_t caddr,
+                           compat_ulong_t cdata)
+{
+       unsigned long addr = caddr;
+       unsigned long data = cdata;
+       void __user *datap = compat_ptr(data);
+       int ret;
+
+       switch (request) {
+       /* Read 32bits at location addr in the USER area.  Only allow
+          to return the lower 32bits of segment and debug registers.  */
+       case PTRACE_PEEKUSR: {
+               u32 tmp;
+
+               ret = -EIO;
+               if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user) ||
+                   addr < offsetof(struct user_regs_struct, cs))
+                       break;
+
+               tmp = 0;  /* Default return condition */
+               if (addr < sizeof(struct user_regs_struct))
+                       tmp = getreg(child, addr);
+               else if (addr >= offsetof(struct user, u_debugreg[0]) &&
+                        addr <= offsetof(struct user, u_debugreg[7])) {
+                       addr -= offsetof(struct user, u_debugreg[0]);
+                       tmp = ptrace_get_debugreg(child, addr / sizeof(data));
+               }
+               ret = put_user(tmp, (__u32 __user *)datap);
+               break;
+       }
+
+       /* Write the word at location addr in the USER area.  Only allow
+          to update segment and debug registers with the upper 32bits
+          zero-extended. */
+       case PTRACE_POKEUSR:
+               ret = -EIO;
+               if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user) ||
+                   addr < offsetof(struct user_regs_struct, cs))
+                       break;
+
+               if (addr < sizeof(struct user_regs_struct))
+                       ret = putreg(child, addr, data);
+               else if (addr >= offsetof(struct user, u_debugreg[0]) &&
+                        addr <= offsetof(struct user, u_debugreg[7])) {
+                       addr -= offsetof(struct user, u_debugreg[0]);
+                       ret = ptrace_set_debugreg(child,
+                                                 addr / sizeof(data), data);
+               }
+               break;
+
+       case PTRACE_GETREGS:    /* Get all gp regs from the child. */
+               return copy_regset_to_user(child,
+                                          task_user_regset_view(current),
+                                          REGSET_GENERAL,
+                                          0, sizeof(struct user_regs_struct),
+                                          datap);
+
+       case PTRACE_SETREGS:    /* Set all gp regs in the child. */
+               return copy_regset_from_user(child,
+                                            task_user_regset_view(current),
+                                            REGSET_GENERAL,
+                                            0, sizeof(struct user_regs_struct),
+                                            datap);
+
+       case PTRACE_GETFPREGS:  /* Get the child FPU state. */
+               return copy_regset_to_user(child,
+                                          task_user_regset_view(current),
+                                          REGSET_FP,
+                                          0, sizeof(struct user_i387_struct),
+                                          datap);
+
+       case PTRACE_SETFPREGS:  /* Set the child FPU state. */
+               return copy_regset_from_user(child,
+                                            task_user_regset_view(current),
+                                            REGSET_FP,
+                                            0, sizeof(struct user_i387_struct),
+                                            datap);
+
+               /* normal 64bit interface to access TLS data.
+                  Works just like arch_prctl, except that the arguments
+                  are reversed. */
+       case PTRACE_ARCH_PRCTL:
+               return do_arch_prctl(child, data, addr);
+
+       default:
+               return compat_ptrace_request(child, request, addr, data);
+       }
+
+       return ret;
+}
+#endif
+
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        compat_ulong_t caddr, compat_ulong_t cdata)
 {
@@ -1140,6 +1234,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
        int ret;
        __u32 val;
 
+#ifdef CONFIG_X86_X32_ABI
+       if (!is_ia32_task())
+               return x32_arch_ptrace(child, request, caddr, cdata);
+#endif
+
        switch (request) {
        case PTRACE_PEEKUSR:
                ret = getreg32(child, addr, &val);
@@ -1327,7 +1426,7 @@ static void fill_sigtrap_info(struct task_struct *tsk,
                                int error_code, int si_code,
                                struct siginfo *info)
 {
-       tsk->thread.trap_no = 1;
+       tsk->thread.trap_nr = X86_TRAP_DB;
        tsk->thread.error_code = error_code;
 
        memset(info, 0, sizeof(*info));
index 88638883176a13052a251704504ec23ab129155b..1a2901562059a48a4ec863c64e4150b881ed9271 100644 (file)
@@ -90,7 +90,6 @@
 #include <asm/processor.h>
 #include <asm/bugs.h>
 
-#include <asm/system.h>
 #include <asm/vsyscall.h>
 #include <asm/cpu.h>
 #include <asm/desc.h>
@@ -509,15 +508,6 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 
 #ifdef CONFIG_KEXEC
 
-static inline unsigned long long get_total_mem(void)
-{
-       unsigned long long total;
-
-       total = max_pfn - min_low_pfn;
-
-       return total << PAGE_SHIFT;
-}
-
 /*
  * Keep the crash kernel below this limit.  On 32 bits earlier kernels
  * would limit the kernel to the low 512 MiB due to mapping restrictions.
@@ -536,7 +526,7 @@ static void __init reserve_crashkernel(void)
        unsigned long long crash_size, crash_base;
        int ret;
 
-       total_mem = get_total_mem();
+       total_mem = memblock_phys_mem_size();
 
        ret = parse_crashkernel(boot_command_line, total_mem,
                        &crash_size, &crash_base);
index 25edcfc9ba5b8587d06f613481dfa2436f972bdb..115eac431483cbc6acc3a01d54f26abcd69d0227 100644 (file)
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/kernel.h>
-#include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
-#include <linux/ptrace.h>
 #include <linux/tracehook.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <asm/fpu-internal.h>
 #include <asm/vdso.h>
 #include <asm/mce.h>
+#include <asm/sighandling.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/proto.h>
 #include <asm/ia32_unistd.h>
+#include <asm/sys_ia32.h>
 #endif /* CONFIG_X86_64 */
 
 #include <asm/syscall.h>
 
 #include <asm/sigframe.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-#define __FIX_EFLAGS   (X86_EFLAGS_AC | X86_EFLAGS_OF | \
-                        X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
-                        X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
-                        X86_EFLAGS_CF)
-
 #ifdef CONFIG_X86_32
 # define FIX_EFLAGS    (__FIX_EFLAGS | X86_EFLAGS_RF)
 #else
@@ -69,9 +62,8 @@
        regs->seg = GET_SEG(seg) | 3;                   \
 } while (0)
 
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
-                  unsigned long *pax)
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
+                      unsigned long *pax)
 {
        void __user *buf;
        unsigned int tmpflags;
@@ -126,9 +118,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
        return err;
 }
 
-static int
-setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
-                struct pt_regs *regs, unsigned long mask)
+int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
+                    struct pt_regs *regs, unsigned long mask)
 {
        int err = 0;
 
@@ -160,7 +151,7 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
                put_user_ex(regs->r15, &sc->r15);
 #endif /* CONFIG_X86_64 */
 
-               put_user_ex(current->thread.trap_no, &sc->trapno);
+               put_user_ex(current->thread.trap_nr, &sc->trapno);
                put_user_ex(current->thread.error_code, &sc->err);
                put_user_ex(regs->ip, &sc->ip);
 #ifdef CONFIG_X86_32
@@ -643,6 +634,16 @@ static int signr_convert(int sig)
 #define is_ia32        0
 #endif /* CONFIG_IA32_EMULATION */
 
+#ifdef CONFIG_X86_X32_ABI
+#define is_x32 test_thread_flag(TIF_X32)
+
+static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
+                             siginfo_t *info, compat_sigset_t *set,
+                             struct pt_regs *regs);
+#else /* !CONFIG_X86_X32_ABI */
+#define is_x32 0
+#endif /* CONFIG_X86_X32_ABI */
+
 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                sigset_t *set, struct pt_regs *regs);
 int ia32_setup_frame(int sig, struct k_sigaction *ka,
@@ -667,8 +668,14 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                        ret = ia32_setup_rt_frame(usig, ka, info, set, regs);
                else
                        ret = ia32_setup_frame(usig, ka, set, regs);
-       } else
+#ifdef CONFIG_X86_X32_ABI
+       } else if (is_x32) {
+               ret = x32_setup_rt_frame(usig, ka, info,
+                                        (compat_sigset_t *)set, regs);
+#endif
+       } else {
                ret = __setup_rt_frame(sig, ka, info, set, regs);
+       }
 
        if (ret) {
                force_sigsegv(sig, current);
@@ -851,3 +858,102 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
 
        force_sig(SIGSEGV, me);
 }
+
+#ifdef CONFIG_X86_X32_ABI
+static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
+                             siginfo_t *info, compat_sigset_t *set,
+                             struct pt_regs *regs)
+{
+       struct rt_sigframe_x32 __user *frame;
+       void __user *restorer;
+       int err = 0;
+       void __user *fpstate = NULL;
+
+       frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
+
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               return -EFAULT;
+
+       if (ka->sa.sa_flags & SA_SIGINFO) {
+               if (copy_siginfo_to_user32(&frame->info, info))
+                       return -EFAULT;
+       }
+
+       put_user_try {
+               /* Create the ucontext.  */
+               if (cpu_has_xsave)
+                       put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+               else
+                       put_user_ex(0, &frame->uc.uc_flags);
+               put_user_ex(0, &frame->uc.uc_link);
+               put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+               put_user_ex(sas_ss_flags(regs->sp),
+                           &frame->uc.uc_stack.ss_flags);
+               put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+               put_user_ex(0, &frame->uc.uc__pad0);
+               err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+                                       regs, set->sig[0]);
+               err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+               if (ka->sa.sa_flags & SA_RESTORER) {
+                       restorer = ka->sa.sa_restorer;
+               } else {
+                       /* could use a vstub here */
+                       restorer = NULL;
+                       err |= -EFAULT;
+               }
+               put_user_ex(restorer, &frame->pretcode);
+       } put_user_catch(err);
+
+       if (err)
+               return -EFAULT;
+
+       /* Set up registers for signal handler */
+       regs->sp = (unsigned long) frame;
+       regs->ip = (unsigned long) ka->sa.sa_handler;
+
+       /* We use the x32 calling convention here... */
+       regs->di = sig;
+       regs->si = (unsigned long) &frame->info;
+       regs->dx = (unsigned long) &frame->uc;
+
+       loadsegment(ds, __USER_DS);
+       loadsegment(es, __USER_DS);
+
+       regs->cs = __USER_CS;
+       regs->ss = __USER_DS;
+
+       return 0;
+}
+
+asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
+{
+       struct rt_sigframe_x32 __user *frame;
+       sigset_t set;
+       unsigned long ax;
+       struct pt_regs tregs;
+
+       frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
+
+       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+               goto badframe;
+
+       sigdelsetmask(&set, ~_BLOCKABLE);
+       set_current_blocked(&set);
+
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+               goto badframe;
+
+       tregs = *regs;
+       if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
+               goto badframe;
+
+       return ax;
+
+badframe:
+       signal_fault(regs, frame, "x32 rt_sigreturn");
+       return 0;
+}
+#endif
index e578a79a3093253038f6b0d9aef4292e9540104a..ce13315d48fb73d9d55f8344e99e6c50bbe168db 100644 (file)
@@ -219,14 +219,9 @@ static void __cpuinit smp_callin(void)
         * Update loops_per_jiffy in cpu_data. Previous call to
         * smp_store_cpu_info() stored a value that is close but not as
         * accurate as the value just calculated.
-        *
-        * Need to enable IRQs because it can take longer and then
-        * the NMI watchdog might kill us.
         */
-       local_irq_enable();
        calibrate_delay();
        cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy;
-       local_irq_disable();
        pr_debug("Stack at about %p\n", &cpuid);
 
        /*
@@ -255,6 +250,7 @@ notrace static void __cpuinit start_secondary(void *unused)
         * most necessary things.
         */
        cpu_init();
+       x86_cpuinit.early_percpu_clock_init();
        preempt_disable();
        smp_callin();
 
index ef59642ff1bf9e719ae1674668dece0a22787d7c..b4d3c3927dd8c4106c840f494ba3fd157d98e554 100644 (file)
@@ -98,7 +98,7 @@ out:
 static void find_start_end(unsigned long flags, unsigned long *begin,
                           unsigned long *end)
 {
-       if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
+       if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT)) {
                unsigned long new_begin;
                /* This is usually used needed to map code in small
                   model, so it needs to be in the first 31bit. Limit
@@ -144,7 +144,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+       if (((flags & MAP_32BIT) || test_thread_flag(TIF_ADDR32))
            && len <= mm->cached_hole_size) {
                mm->cached_hole_size = 0;
                mm->free_area_cache = begin;
@@ -205,7 +205,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                return addr;
 
        /* for MAP_32BIT mappings we force the legact mmap base */
-       if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT))
+       if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT))
                goto bottomup;
 
        /* requesting a specific address */
index 7ac7943be02cb0bb69577daa0403b08372d82da4..5c7f8c20da74c21ffa827778d0c53b0b2bb11e8a 100644 (file)
@@ -5,6 +5,14 @@
 #include <linux/cache.h>
 #include <asm/asm-offsets.h>
 
+#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
+
+#ifdef CONFIG_X86_X32_ABI
+# define __SYSCALL_X32(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
+#else
+# define __SYSCALL_X32(nr, sym, compat) /* nothing */
+#endif
+
 #define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ;
 #include <asm/syscalls_64.h>
 #undef __SYSCALL_64
index 9e540fee70096f692a5179dc3ea9d21d687a14cf..ab40954e113e952b088818e60b569cabc96488f5 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/tce.h>
 #include <asm/calgary.h>
 #include <asm/proto.h>
+#include <asm/cacheflush.h>
 
 /* flush a tce at 'tceaddr' to main memory */
 static inline void flush_tce(void* tceaddr)
index 6bb7b8579e70e0a73a67ddcb9f69c01696bb6413..9d9d2f9e77a5a18e318a64915e17008e82aa0537 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/proto.h>
@@ -163,7 +162,7 @@ int regset_tls_get(struct task_struct *target, const struct user_regset *regset,
 {
        const struct desc_struct *tls;
 
-       if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+       if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
            (pos % sizeof(struct user_desc)) != 0 ||
            (count % sizeof(struct user_desc)) != 0)
                return -EINVAL;
@@ -198,7 +197,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
        struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
        const struct user_desc *info;
 
-       if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+       if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
            (pos % sizeof(struct user_desc)) != 0 ||
            (count % sizeof(struct user_desc)) != 0)
                return -EINVAL;
index ec61d4c1b93be537593e738263119c53c6de27fc..ff9281f1602913a56f8b017d05b3712f37daa27b 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/processor.h>
 #include <asm/debugreg.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
@@ -120,7 +119,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
                 * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
                 * On nmi (interrupt 2), do_trap should not be called.
                 */
-               if (trapnr < 6)
+               if (trapnr < X86_TRAP_UD)
                        goto vm86_trap;
                goto trap_signal;
        }
@@ -133,7 +132,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
 trap_signal:
 #endif
        /*
-        * We want error_code and trap_no set for userspace faults and
+        * We want error_code and trap_nr set for userspace faults and
         * kernelspace faults which result in die(), but not
         * kernelspace faults which are fixed up.  die() gives the
         * process no chance to handle the signal and notice the
@@ -142,7 +141,7 @@ trap_signal:
         * delivered, faults.  See also do_general_protection below.
         */
        tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = trapnr;
+       tsk->thread.trap_nr = trapnr;
 
 #ifdef CONFIG_X86_64
        if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
@@ -165,7 +164,7 @@ trap_signal:
 kernel_trap:
        if (!fixup_exception(regs)) {
                tsk->thread.error_code = error_code;
-               tsk->thread.trap_no = trapnr;
+               tsk->thread.trap_nr = trapnr;
                die(str, regs, error_code);
        }
        return;
@@ -204,27 +203,31 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code)       \
        do_trap(trapnr, signr, str, regs, error_code, &info);           \
 }
 
-DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
-DO_ERROR(4, SIGSEGV, "overflow", overflow)
-DO_ERROR(5, SIGSEGV, "bounds", bounds)
-DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
-DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
-DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
+               regs->ip)
+DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow)
+DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds)
+DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN,
+               regs->ip)
+DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun",
+               coprocessor_segment_overrun)
+DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS)
+DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present)
 #ifdef CONFIG_X86_32
-DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment)
 #endif
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check,
+               BUS_ADRALN, 0)
 
 #ifdef CONFIG_X86_64
 /* Runs on IST stack */
 dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
 {
        if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
-                       12, SIGBUS) == NOTIFY_STOP)
+                       X86_TRAP_SS, SIGBUS) == NOTIFY_STOP)
                return;
        preempt_conditional_sti(regs);
-       do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
+       do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
        preempt_conditional_cli(regs);
 }
 
@@ -234,10 +237,10 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
        struct task_struct *tsk = current;
 
        /* Return not checked because double check cannot be ignored */
-       notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
+       notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
 
        tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 8;
+       tsk->thread.trap_nr = X86_TRAP_DF;
 
        /*
         * This is always a kernel trap and never fixable (and thus must
@@ -265,7 +268,7 @@ do_general_protection(struct pt_regs *regs, long error_code)
                goto gp_in_kernel;
 
        tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
+       tsk->thread.trap_nr = X86_TRAP_GP;
 
        if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
                        printk_ratelimit()) {
@@ -292,9 +295,9 @@ gp_in_kernel:
                return;
 
        tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
-       if (notify_die(DIE_GPF, "general protection fault", regs,
-                               error_code, 13, SIGSEGV) == NOTIFY_STOP)
+       tsk->thread.trap_nr = X86_TRAP_GP;
+       if (notify_die(DIE_GPF, "general protection fault", regs, error_code,
+                       X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP)
                return;
        die("general protection fault", regs, error_code);
 }
@@ -303,13 +306,13 @@ gp_in_kernel:
 dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
-       if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
-                       == NOTIFY_STOP)
+       if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
+                               SIGTRAP) == NOTIFY_STOP)
                return;
 #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
 
-       if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
-                       == NOTIFY_STOP)
+       if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
+                       SIGTRAP) == NOTIFY_STOP)
                return;
 
        /*
@@ -318,7 +321,7 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
         */
        debug_stack_usage_inc();
        preempt_conditional_sti(regs);
-       do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
+       do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
        preempt_conditional_cli(regs);
        debug_stack_usage_dec();
 }
@@ -423,8 +426,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
        preempt_conditional_sti(regs);
 
        if (regs->flags & X86_VM_MASK) {
-               handle_vm86_trap((struct kernel_vm86_regs *) regs,
-                               error_code, 1);
+               handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
+                                       X86_TRAP_DB);
                preempt_conditional_cli(regs);
                debug_stack_usage_dec();
                return;
@@ -461,7 +464,8 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)
        struct task_struct *task = current;
        siginfo_t info;
        unsigned short err;
-       char *str = (trapnr == 16) ? "fpu exception" : "simd exception";
+       char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" :
+                                               "simd exception";
 
        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
                return;
@@ -471,7 +475,7 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)
        {
                if (!fixup_exception(regs)) {
                        task->thread.error_code = error_code;
-                       task->thread.trap_no = trapnr;
+                       task->thread.trap_nr = trapnr;
                        die(str, regs, error_code);
                }
                return;
@@ -481,12 +485,12 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)
         * Save the info for the exception handler and clear the error.
         */
        save_init_fpu(task);
-       task->thread.trap_no = trapnr;
+       task->thread.trap_nr = trapnr;
        task->thread.error_code = error_code;
        info.si_signo = SIGFPE;
        info.si_errno = 0;
        info.si_addr = (void __user *)regs->ip;
-       if (trapnr == 16) {
+       if (trapnr == X86_TRAP_MF) {
                unsigned short cwd, swd;
                /*
                 * (~cwd & swd) will mask out exceptions that are not set to unmasked
@@ -530,10 +534,11 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)
                info.si_code = FPE_FLTRES;
        } else {
                /*
-                * If we're using IRQ 13, or supposedly even some trap 16
-                * implementations, it's possible we get a spurious trap...
+                * If we're using IRQ 13, or supposedly even some trap
+                * X86_TRAP_MF implementations, it's possible
+                * we get a spurious trap, which is not an error.
                 */
-               return;         /* Spurious trap, no error */
+               return;
        }
        force_sig_info(SIGFPE, &info, task);
 }
@@ -544,13 +549,13 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
        ignore_fpu_irq = 1;
 #endif
 
-       math_error(regs, error_code, 16);
+       math_error(regs, error_code, X86_TRAP_MF);
 }
 
 dotraplinkage void
 do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
 {
-       math_error(regs, error_code, 19);
+       math_error(regs, error_code, X86_TRAP_XF);
 }
 
 dotraplinkage void
@@ -644,20 +649,21 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
        info.si_errno = 0;
        info.si_code = ILL_BADSTK;
        info.si_addr = NULL;
-       if (notify_die(DIE_TRAP, "iret exception",
-                       regs, error_code, 32, SIGILL) == NOTIFY_STOP)
+       if (notify_die(DIE_TRAP, "iret exception", regs, error_code,
+                       X86_TRAP_IRET, SIGILL) == NOTIFY_STOP)
                return;
-       do_trap(32, SIGILL, "iret exception", regs, error_code, &info);
+       do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
+               &info);
 }
 #endif
 
 /* Set of traps needed for early debugging. */
 void __init early_trap_init(void)
 {
-       set_intr_gate_ist(1, &debug, DEBUG_STACK);
+       set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
        /* int3 can be called from all */
-       set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
-       set_intr_gate(14, &page_fault);
+       set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK);
+       set_intr_gate(X86_TRAP_PF, &page_fault);
        load_idt(&idt_descr);
 }
 
@@ -673,30 +679,30 @@ void __init trap_init(void)
        early_iounmap(p, 4);
 #endif
 
-       set_intr_gate(0, &divide_error);
-       set_intr_gate_ist(2, &nmi, NMI_STACK);
+       set_intr_gate(X86_TRAP_DE, &divide_error);
+       set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
        /* int4 can be called from all */
-       set_system_intr_gate(4, &overflow);
-       set_intr_gate(5, &bounds);
-       set_intr_gate(6, &invalid_op);
-       set_intr_gate(7, &device_not_available);
+       set_system_intr_gate(X86_TRAP_OF, &overflow);
+       set_intr_gate(X86_TRAP_BR, &bounds);
+       set_intr_gate(X86_TRAP_UD, &invalid_op);
+       set_intr_gate(X86_TRAP_NM, &device_not_available);
 #ifdef CONFIG_X86_32
-       set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS);
+       set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
 #else
-       set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK);
+       set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
 #endif
-       set_intr_gate(9, &coprocessor_segment_overrun);
-       set_intr_gate(10, &invalid_TSS);
-       set_intr_gate(11, &segment_not_present);
-       set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
-       set_intr_gate(13, &general_protection);
-       set_intr_gate(15, &spurious_interrupt_bug);
-       set_intr_gate(16, &coprocessor_error);
-       set_intr_gate(17, &alignment_check);
+       set_intr_gate(X86_TRAP_OLD_MF, &coprocessor_segment_overrun);
+       set_intr_gate(X86_TRAP_TS, &invalid_TSS);
+       set_intr_gate(X86_TRAP_NP, &segment_not_present);
+       set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK);
+       set_intr_gate(X86_TRAP_GP, &general_protection);
+       set_intr_gate(X86_TRAP_SPURIOUS, &spurious_interrupt_bug);
+       set_intr_gate(X86_TRAP_MF, &coprocessor_error);
+       set_intr_gate(X86_TRAP_AC, &alignment_check);
 #ifdef CONFIG_X86_MCE
-       set_intr_gate_ist(18, &machine_check, MCE_STACK);
+       set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
 #endif
-       set_intr_gate(19, &simd_coprocessor_error);
+       set_intr_gate(X86_TRAP_XF, &simd_coprocessor_error);
 
        /* Reserve all the builtin and the syscall vector: */
        for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
@@ -721,7 +727,7 @@ void __init trap_init(void)
 
 #ifdef CONFIG_X86_64
        memcpy(&nmi_idt_table, &idt_table, IDT_ENTRIES * 16);
-       set_nmi_gate(1, &debug);
-       set_nmi_gate(3, &int3);
+       set_nmi_gate(X86_TRAP_DB, &debug);
+       set_nmi_gate(X86_TRAP_BP, &int3);
 #endif
 }
index 183c5925a9fec5f44b46476468bebc69f4e82ffd..fc0a147e372726fb019b8873969dc1fca3e43109 100644 (file)
@@ -630,7 +630,7 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
 
 static unsigned long long cyc2ns_suspend;
 
-void save_sched_clock_state(void)
+void tsc_save_sched_clock_state(void)
 {
        if (!sched_clock_stable)
                return;
@@ -646,7 +646,7 @@ void save_sched_clock_state(void)
  * that sched_clock() continues from the point where it was left off during
  * suspend.
  */
-void restore_sched_clock_state(void)
+void tsc_restore_sched_clock_state(void)
 {
        unsigned long long offset;
        unsigned long flags;
@@ -933,6 +933,16 @@ static int __init init_tsc_clocksource(void)
                clocksource_tsc.rating = 0;
                clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
        }
+
+       /*
+        * Trust the results of the earlier calibration on systems
+        * exporting a reliable TSC.
+        */
+       if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
+               clocksource_register_khz(&clocksource_tsc, tsc_khz);
+               return 0;
+       }
+
        schedule_delayed_work(&tsc_irqwork, 0);
        return 0;
 }
index 328cb37bb827915ccc3e87cc6518acd7ccf25686..255f58ae71e8991838080eac595786a60f372a62 100644 (file)
@@ -569,7 +569,7 @@ int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
        }
        if (trapno != 1)
                return 1; /* we let this handle by the calling routine */
-       current->thread.trap_no = trapno;
+       current->thread.trap_nr = trapno;
        current->thread.error_code = error_code;
        force_sig(SIGTRAP, current);
        return 0;
index b07ba9393564ddce2413cbc07e8fec27f47fa9c9..f386dc49f988d753c5b9f8167c80313d5be72178 100644 (file)
 #include "vsyscall_trace.h"
 
 DEFINE_VVAR(int, vgetcpu_mode);
-DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =
-{
-       .lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),
-};
+DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
 
 static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
 
@@ -80,20 +77,15 @@ early_param("vsyscall", vsyscall_setup);
 
 void update_vsyscall_tz(void)
 {
-       unsigned long flags;
-
-       write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
-       /* sys_tz has changed */
        vsyscall_gtod_data.sys_tz = sys_tz;
-       write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
 }
 
 void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
                        struct clocksource *clock, u32 mult)
 {
-       unsigned long flags;
+       struct timespec monotonic;
 
-       write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+       write_seqcount_begin(&vsyscall_gtod_data.seq);
 
        /* copy vsyscall data */
        vsyscall_gtod_data.clock.vclock_mode    = clock->archdata.vclock_mode;
@@ -101,12 +93,19 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
        vsyscall_gtod_data.clock.mask           = clock->mask;
        vsyscall_gtod_data.clock.mult           = mult;
        vsyscall_gtod_data.clock.shift          = clock->shift;
+
        vsyscall_gtod_data.wall_time_sec        = wall_time->tv_sec;
        vsyscall_gtod_data.wall_time_nsec       = wall_time->tv_nsec;
-       vsyscall_gtod_data.wall_to_monotonic    = *wtm;
+
+       monotonic = timespec_add(*wall_time, *wtm);
+       vsyscall_gtod_data.monotonic_time_sec   = monotonic.tv_sec;
+       vsyscall_gtod_data.monotonic_time_nsec  = monotonic.tv_nsec;
+
        vsyscall_gtod_data.wall_time_coarse     = __current_kernel_time();
+       vsyscall_gtod_data.monotonic_time_coarse =
+               timespec_add(vsyscall_gtod_data.wall_time_coarse, *wtm);
 
-       write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+       write_seqcount_end(&vsyscall_gtod_data.seq);
 }
 
 static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
@@ -153,7 +152,7 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
 
                thread->error_code      = 6;  /* user fault, no page, write */
                thread->cr2             = ptr;
-               thread->trap_no         = 14;
+               thread->trap_nr         = X86_TRAP_PF;
 
                memset(&info, 0, sizeof(info));
                info.si_signo           = SIGSEGV;
index 947a06ccc67305d014dd558a68be75f0f8a34c11..e9f265fd79ae11db4d5234e7b7462134c6220619 100644 (file)
@@ -91,6 +91,7 @@ struct x86_init_ops x86_init __initdata = {
 };
 
 struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
+       .early_percpu_clock_init        = x86_init_noop,
        .setup_percpu_clockev           = setup_secondary_APIC_clock,
        .fixup_cpu_id                   = x86_default_fixup_cpu_id,
 };
@@ -107,7 +108,9 @@ struct x86_platform_ops x86_platform = {
        .is_untracked_pat_range         = is_ISA_range,
        .nmi_init                       = default_nmi_init,
        .get_nmi_reason                 = default_get_nmi_reason,
-       .i8042_detect                   = default_i8042_detect
+       .i8042_detect                   = default_i8042_detect,
+       .save_sched_clock_state         = tsc_save_sched_clock_state,
+       .restore_sched_clock_state      = tsc_restore_sched_clock_state,
 };
 
 EXPORT_SYMBOL_GPL(x86_platform);
index 89b02bfaaca56e38dfc683707047538091a5f6fb..9fed5bedaad6a90b61b5b7300bde5f6f5deee74f 100644 (file)
@@ -236,7 +236,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
        const u32 kvm_supported_word6_x86_features =
                F(LAHF_LM) | F(CMP_LEGACY) | 0 /*SVM*/ | 0 /* ExtApicSpace */ |
                F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
-               F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) |
+               F(3DNOWPREFETCH) | F(OSVW) | 0 /* IBS */ | F(XOP) |
                0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
 
        /* cpuid 0xC0000001.edx */
index 5b97e1797a6d1411116445fc5775aa2bc826933b..26d1fb437eb511f0548ae8953c2f289932ff6436 100644 (file)
@@ -43,4 +43,12 @@ static inline bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
        return best && (best->ebx & bit(X86_FEATURE_FSGSBASE));
 }
 
+static inline bool guest_cpuid_has_osvw(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
+       return best && (best->ecx & bit(X86_FEATURE_OSVW));
+}
+
 #endif
index 0982507b962a736f3e643d454d4b38c2b1cd1c29..83756223f8aa770b049f980f81fa5b640f697f72 100644 (file)
@@ -57,6 +57,7 @@
 #define OpDS              23ull  /* DS */
 #define OpFS              24ull  /* FS */
 #define OpGS              25ull  /* GS */
+#define OpMem8            26ull  /* 8-bit zero extended memory operand */
 
 #define OpBits             5  /* Width of operand field */
 #define OpMask             ((1ull << OpBits) - 1)
 #define SrcAcc      (OpAcc << SrcShift)
 #define SrcImmU16   (OpImmU16 << SrcShift)
 #define SrcDX       (OpDX << SrcShift)
+#define SrcMem8     (OpMem8 << SrcShift)
 #define SrcMask     (OpMask << SrcShift)
 #define BitOp       (1<<11)
 #define MemAbs      (1<<12)      /* Memory operand is absolute displacement */
@@ -858,8 +860,7 @@ static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
 }
 
 static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
-                                   struct operand *op,
-                                   int inhibit_bytereg)
+                                   struct operand *op)
 {
        unsigned reg = ctxt->modrm_reg;
        int highbyte_regs = ctxt->rex_prefix == 0;
@@ -876,7 +877,7 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
        }
 
        op->type = OP_REG;
-       if ((ctxt->d & ByteOp) && !inhibit_bytereg) {
+       if (ctxt->d & ByteOp) {
                op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs);
                op->bytes = 1;
        } else {
@@ -1151,6 +1152,22 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
        return 1;
 }
 
+static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt,
+                                    u16 index, struct desc_struct *desc)
+{
+       struct desc_ptr dt;
+       ulong addr;
+
+       ctxt->ops->get_idt(ctxt, &dt);
+
+       if (dt.size < index * 8 + 7)
+               return emulate_gp(ctxt, index << 3 | 0x2);
+
+       addr = dt.address + index * 8;
+       return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc,
+                                  &ctxt->exception);
+}
+
 static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
                                     u16 selector, struct desc_ptr *dt)
 {
@@ -1227,6 +1244,8 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                seg_desc.type = 3;
                seg_desc.p = 1;
                seg_desc.s = 1;
+               if (ctxt->mode == X86EMUL_MODE_VM86)
+                       seg_desc.dpl = 3;
                goto load;
        }
 
@@ -1891,6 +1910,17 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
        ss->p = 1;
 }
 
+static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
+{
+       u32 eax, ebx, ecx, edx;
+
+       eax = ecx = 0;
+       return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)
+               && ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
+               && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
+               && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
+}
+
 static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 {
        struct x86_emulate_ops *ops = ctxt->ops;
@@ -2007,6 +2037,14 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        if (ctxt->mode == X86EMUL_MODE_REAL)
                return emulate_gp(ctxt, 0);
 
+       /*
+        * Not recognized on AMD in compat mode (but is recognized in legacy
+        * mode).
+        */
+       if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
+           && !vendor_intel(ctxt))
+               return emulate_ud(ctxt);
+
        /* XXX sysenter/sysexit have not been tested in 64bit mode.
        * Therefore, we inject an #UD.
        */
@@ -2306,6 +2344,8 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
                return emulate_gp(ctxt, 0);
        ctxt->_eip = tss->eip;
        ctxt->eflags = tss->eflags | 2;
+
+       /* General purpose registers */
        ctxt->regs[VCPU_REGS_RAX] = tss->eax;
        ctxt->regs[VCPU_REGS_RCX] = tss->ecx;
        ctxt->regs[VCPU_REGS_RDX] = tss->edx;
@@ -2327,6 +2367,24 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
        set_segment_selector(ctxt, tss->fs, VCPU_SREG_FS);
        set_segment_selector(ctxt, tss->gs, VCPU_SREG_GS);
 
+       /*
+        * If we're switching between Protected Mode and VM86, we need to make
+        * sure to update the mode before loading the segment descriptors so
+        * that the selectors are interpreted correctly.
+        *
+        * Need to get rflags to the vcpu struct immediately because it
+        * influences the CPL which is checked at least when loading the segment
+        * descriptors and when pushing an error code to the new kernel stack.
+        *
+        * TODO Introduce a separate ctxt->ops->set_cpl callback
+        */
+       if (ctxt->eflags & X86_EFLAGS_VM)
+               ctxt->mode = X86EMUL_MODE_VM86;
+       else
+               ctxt->mode = X86EMUL_MODE_PROT32;
+
+       ctxt->ops->set_rflags(ctxt, ctxt->eflags);
+
        /*
         * Now load segment descriptors. If fault happenes at this stage
         * it is handled in a context of new task
@@ -2401,7 +2459,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
 }
 
 static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
-                                  u16 tss_selector, int reason,
+                                  u16 tss_selector, int idt_index, int reason,
                                   bool has_error_code, u32 error_code)
 {
        struct x86_emulate_ops *ops = ctxt->ops;
@@ -2423,12 +2481,35 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 
        /* FIXME: check that next_tss_desc is tss */
 
-       if (reason != TASK_SWITCH_IRET) {
-               if ((tss_selector & 3) > next_tss_desc.dpl ||
-                   ops->cpl(ctxt) > next_tss_desc.dpl)
-                       return emulate_gp(ctxt, 0);
+       /*
+        * Check privileges. The three cases are task switch caused by...
+        *
+        * 1. jmp/call/int to task gate: Check against DPL of the task gate
+        * 2. Exception/IRQ/iret: No check is performed
+        * 3. jmp/call to TSS: Check agains DPL of the TSS
+        */
+       if (reason == TASK_SWITCH_GATE) {
+               if (idt_index != -1) {
+                       /* Software interrupts */
+                       struct desc_struct task_gate_desc;
+                       int dpl;
+
+                       ret = read_interrupt_descriptor(ctxt, idt_index,
+                                                       &task_gate_desc);
+                       if (ret != X86EMUL_CONTINUE)
+                               return ret;
+
+                       dpl = task_gate_desc.dpl;
+                       if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl)
+                               return emulate_gp(ctxt, (idt_index << 3) | 0x2);
+               }
+       } else if (reason != TASK_SWITCH_IRET) {
+               int dpl = next_tss_desc.dpl;
+               if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl)
+                       return emulate_gp(ctxt, tss_selector);
        }
 
+
        desc_limit = desc_limit_scaled(&next_tss_desc);
        if (!next_tss_desc.p ||
            ((desc_limit < 0x67 && (next_tss_desc.type & 8)) ||
@@ -2481,7 +2562,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 }
 
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
-                        u16 tss_selector, int reason,
+                        u16 tss_selector, int idt_index, int reason,
                         bool has_error_code, u32 error_code)
 {
        int rc;
@@ -2489,7 +2570,7 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
        ctxt->_eip = ctxt->eip;
        ctxt->dst.type = OP_NONE;
 
-       rc = emulator_do_task_switch(ctxt, tss_selector, reason,
+       rc = emulator_do_task_switch(ctxt, tss_selector, idt_index, reason,
                                     has_error_code, error_code);
 
        if (rc == X86EMUL_CONTINUE)
@@ -3514,13 +3595,13 @@ static struct opcode twobyte_table[256] = {
        I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr),
        I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
        I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg),
-       D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
+       D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
        /* 0xB8 - 0xBF */
        N, N,
        G(BitOp, group8),
        I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc),
        I(DstReg | SrcMem | ModRM, em_bsf), I(DstReg | SrcMem | ModRM, em_bsr),
-       D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
+       D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
        /* 0xC0 - 0xCF */
        D2bv(DstMem | SrcReg | ModRM | Lock),
        N, D(DstMem | SrcReg | ModRM | Mov),
@@ -3602,9 +3683,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
 
        switch (d) {
        case OpReg:
-               decode_register_operand(ctxt, op,
-                        op == &ctxt->dst &&
-                        ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
+               decode_register_operand(ctxt, op);
                break;
        case OpImmUByte:
                rc = decode_imm(ctxt, op, 1, false);
@@ -3656,6 +3735,9 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
        case OpImm:
                rc = decode_imm(ctxt, op, imm_size(ctxt), true);
                break;
+       case OpMem8:
+               ctxt->memop.bytes = 1;
+               goto mem_common;
        case OpMem16:
                ctxt->memop.bytes = 2;
                goto mem_common;
index b6a73537e1efd2270a00d52612342ed168081b55..81cf4fa4a2bea8f35eeb8a68c30bdb3b18564271 100644 (file)
@@ -307,6 +307,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                if (val & 0x10) {
                        s->init4 = val & 1;
                        s->last_irr = 0;
+                       s->irr &= s->elcr;
                        s->imr = 0;
                        s->priority_add = 0;
                        s->special_mask = 0;
index 31bfc6927bc0a25eae47da65e0884365e8fc4439..858432287ab626dee9ce4568404fdf4f968a89a2 100644 (file)
@@ -433,7 +433,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                break;
 
        case APIC_DM_INIT:
-               if (level) {
+               if (!trig_mode || level) {
                        result = 1;
                        vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
                        kvm_make_request(KVM_REQ_EVENT, vcpu);
@@ -731,7 +731,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
                u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
                u64 ns = 0;
                struct kvm_vcpu *vcpu = apic->vcpu;
-               unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+               unsigned long this_tsc_khz = vcpu->arch.virtual_tsc_khz;
                unsigned long flags;
 
                if (unlikely(!tscdeadline || !this_tsc_khz))
index 224b02c3cda91683afed63cccc5e794fadef4559..4cb164268846302ac5acc122bc434246b4175605 100644 (file)
@@ -688,9 +688,8 @@ static struct kvm_lpage_info *lpage_info_slot(gfn_t gfn,
 {
        unsigned long idx;
 
-       idx = (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
-             (slot->base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
-       return &slot->lpage_info[level - 2][idx];
+       idx = gfn_to_index(gfn, slot->base_gfn, level);
+       return &slot->arch.lpage_info[level - 2][idx];
 }
 
 static void account_shadowed(struct kvm *kvm, gfn_t gfn)
@@ -946,7 +945,7 @@ static void pte_list_walk(unsigned long *pte_list, pte_list_walk_fn fn)
        }
 }
 
-static unsigned long *__gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level,
+static unsigned long *__gfn_to_rmap(gfn_t gfn, int level,
                                    struct kvm_memory_slot *slot)
 {
        struct kvm_lpage_info *linfo;
@@ -966,7 +965,7 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
        struct kvm_memory_slot *slot;
 
        slot = gfn_to_memslot(kvm, gfn);
-       return __gfn_to_rmap(kvm, gfn, level, slot);
+       return __gfn_to_rmap(gfn, level, slot);
 }
 
 static bool rmap_can_add(struct kvm_vcpu *vcpu)
@@ -988,7 +987,7 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
        return pte_list_add(vcpu, spte, rmapp);
 }
 
-static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte)
+static u64 *rmap_next(unsigned long *rmapp, u64 *spte)
 {
        return pte_list_next(rmapp, spte);
 }
@@ -1018,8 +1017,8 @@ int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
        u64 *spte;
        int i, write_protected = 0;
 
-       rmapp = __gfn_to_rmap(kvm, gfn, PT_PAGE_TABLE_LEVEL, slot);
-       spte = rmap_next(kvm, rmapp, NULL);
+       rmapp = __gfn_to_rmap(gfn, PT_PAGE_TABLE_LEVEL, slot);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                BUG_ON(!(*spte & PT_PRESENT_MASK));
                rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
@@ -1027,14 +1026,14 @@ int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
                        mmu_spte_update(spte, *spte & ~PT_WRITABLE_MASK);
                        write_protected = 1;
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
 
        /* check for huge page mappings */
        for (i = PT_DIRECTORY_LEVEL;
             i < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++i) {
-               rmapp = __gfn_to_rmap(kvm, gfn, i, slot);
-               spte = rmap_next(kvm, rmapp, NULL);
+               rmapp = __gfn_to_rmap(gfn, i, slot);
+               spte = rmap_next(rmapp, NULL);
                while (spte) {
                        BUG_ON(!(*spte & PT_PRESENT_MASK));
                        BUG_ON(!is_large_pte(*spte));
@@ -1045,7 +1044,7 @@ int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
                                spte = NULL;
                                write_protected = 1;
                        }
-                       spte = rmap_next(kvm, rmapp, spte);
+                       spte = rmap_next(rmapp, spte);
                }
        }
 
@@ -1066,7 +1065,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
        u64 *spte;
        int need_tlb_flush = 0;
 
-       while ((spte = rmap_next(kvm, rmapp, NULL))) {
+       while ((spte = rmap_next(rmapp, NULL))) {
                BUG_ON(!(*spte & PT_PRESENT_MASK));
                rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte);
                drop_spte(kvm, spte);
@@ -1085,14 +1084,14 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
 
        WARN_ON(pte_huge(*ptep));
        new_pfn = pte_pfn(*ptep);
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                BUG_ON(!is_shadow_present_pte(*spte));
                rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte);
                need_flush = 1;
                if (pte_write(*ptep)) {
                        drop_spte(kvm, spte);
-                       spte = rmap_next(kvm, rmapp, NULL);
+                       spte = rmap_next(rmapp, NULL);
                } else {
                        new_spte = *spte &~ (PT64_BASE_ADDR_MASK);
                        new_spte |= (u64)new_pfn << PAGE_SHIFT;
@@ -1102,7 +1101,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        new_spte &= ~shadow_accessed_mask;
                        mmu_spte_clear_track_bits(spte);
                        mmu_spte_set(spte, new_spte);
-                       spte = rmap_next(kvm, rmapp, spte);
+                       spte = rmap_next(rmapp, spte);
                }
        }
        if (need_flush)
@@ -1176,7 +1175,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
        if (!shadow_accessed_mask)
                return kvm_unmap_rmapp(kvm, rmapp, data);
 
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                int _young;
                u64 _spte = *spte;
@@ -1186,7 +1185,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        young = 1;
                        clear_bit(PT_ACCESSED_SHIFT, (unsigned long *)spte);
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
        return young;
 }
@@ -1205,7 +1204,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
        if (!shadow_accessed_mask)
                goto out;
 
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                u64 _spte = *spte;
                BUG_ON(!(_spte & PT_PRESENT_MASK));
@@ -1214,7 +1213,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        young = 1;
                        break;
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
 out:
        return young;
@@ -1391,11 +1390,6 @@ struct kvm_mmu_pages {
        unsigned int nr;
 };
 
-#define for_each_unsync_children(bitmap, idx)          \
-       for (idx = find_first_bit(bitmap, 512);         \
-            idx < 512;                                 \
-            idx = find_next_bit(bitmap, 512, idx+1))
-
 static int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp,
                         int idx)
 {
@@ -1417,7 +1411,7 @@ static int __mmu_unsync_walk(struct kvm_mmu_page *sp,
 {
        int i, ret, nr_unsync_leaf = 0;
 
-       for_each_unsync_children(sp->unsync_child_bitmap, i) {
+       for_each_set_bit(i, sp->unsync_child_bitmap, 512) {
                struct kvm_mmu_page *child;
                u64 ent = sp->spt[i];
 
@@ -1803,6 +1797,7 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
 {
        if (is_large_pte(*sptep)) {
                drop_spte(vcpu->kvm, sptep);
+               --vcpu->kvm->stat.lpages;
                kvm_flush_remote_tlbs(vcpu->kvm);
        }
 }
@@ -3190,15 +3185,14 @@ static bool sync_mmio_spte(u64 *sptep, gfn_t gfn, unsigned access,
 #undef PTTYPE
 
 static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
-                                 struct kvm_mmu *context,
-                                 int level)
+                                 struct kvm_mmu *context)
 {
        int maxphyaddr = cpuid_maxphyaddr(vcpu);
        u64 exb_bit_rsvd = 0;
 
        if (!context->nx)
                exb_bit_rsvd = rsvd_bits(63, 63);
-       switch (level) {
+       switch (context->root_level) {
        case PT32_ROOT_LEVEL:
                /* no rsvd bits for 2 level 4K page table entries */
                context->rsvd_bits_mask[0][1] = 0;
@@ -3256,8 +3250,9 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
                                        int level)
 {
        context->nx = is_nx(vcpu);
+       context->root_level = level;
 
-       reset_rsvds_bits_mask(vcpu, context, level);
+       reset_rsvds_bits_mask(vcpu, context);
 
        ASSERT(is_pae(vcpu));
        context->new_cr3 = paging_new_cr3;
@@ -3267,7 +3262,6 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
        context->invlpg = paging64_invlpg;
        context->update_pte = paging64_update_pte;
        context->free = paging_free;
-       context->root_level = level;
        context->shadow_root_level = level;
        context->root_hpa = INVALID_PAGE;
        context->direct_map = false;
@@ -3284,8 +3278,9 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
                                 struct kvm_mmu *context)
 {
        context->nx = false;
+       context->root_level = PT32_ROOT_LEVEL;
 
-       reset_rsvds_bits_mask(vcpu, context, PT32_ROOT_LEVEL);
+       reset_rsvds_bits_mask(vcpu, context);
 
        context->new_cr3 = paging_new_cr3;
        context->page_fault = paging32_page_fault;
@@ -3294,7 +3289,6 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
        context->sync_page = paging32_sync_page;
        context->invlpg = paging32_invlpg;
        context->update_pte = paging32_update_pte;
-       context->root_level = PT32_ROOT_LEVEL;
        context->shadow_root_level = PT32E_ROOT_LEVEL;
        context->root_hpa = INVALID_PAGE;
        context->direct_map = false;
@@ -3325,7 +3319,6 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
        context->get_cr3 = get_cr3;
        context->get_pdptr = kvm_pdptr_read;
        context->inject_page_fault = kvm_inject_page_fault;
-       context->nx = is_nx(vcpu);
 
        if (!is_paging(vcpu)) {
                context->nx = false;
@@ -3333,19 +3326,19 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
                context->root_level = 0;
        } else if (is_long_mode(vcpu)) {
                context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, context, PT64_ROOT_LEVEL);
-               context->gva_to_gpa = paging64_gva_to_gpa;
                context->root_level = PT64_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, context);
+               context->gva_to_gpa = paging64_gva_to_gpa;
        } else if (is_pae(vcpu)) {
                context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, context, PT32E_ROOT_LEVEL);
-               context->gva_to_gpa = paging64_gva_to_gpa;
                context->root_level = PT32E_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, context);
+               context->gva_to_gpa = paging64_gva_to_gpa;
        } else {
                context->nx = false;
-               reset_rsvds_bits_mask(vcpu, context, PT32_ROOT_LEVEL);
-               context->gva_to_gpa = paging32_gva_to_gpa;
                context->root_level = PT32_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, context);
+               context->gva_to_gpa = paging32_gva_to_gpa;
        }
 
        return 0;
@@ -3408,18 +3401,18 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
                g_context->gva_to_gpa = nonpaging_gva_to_gpa_nested;
        } else if (is_long_mode(vcpu)) {
                g_context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, g_context, PT64_ROOT_LEVEL);
                g_context->root_level = PT64_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, g_context);
                g_context->gva_to_gpa = paging64_gva_to_gpa_nested;
        } else if (is_pae(vcpu)) {
                g_context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, g_context, PT32E_ROOT_LEVEL);
                g_context->root_level = PT32E_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, g_context);
                g_context->gva_to_gpa = paging64_gva_to_gpa_nested;
        } else {
                g_context->nx = false;
-               reset_rsvds_bits_mask(vcpu, g_context, PT32_ROOT_LEVEL);
                g_context->root_level = PT32_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, g_context);
                g_context->gva_to_gpa = paging32_gva_to_gpa_nested;
        }
 
@@ -3555,7 +3548,7 @@ static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
  * If we're seeing too many writes to a page, it may no longer be a page table,
  * or we may be forking, in which case it is better to unmap the page.
  */
-static bool detect_write_flooding(struct kvm_mmu_page *sp, u64 *spte)
+static bool detect_write_flooding(struct kvm_mmu_page *sp)
 {
        /*
         * Skip write-flooding detected for the sp whose level is 1, because
@@ -3664,10 +3657,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 
        mask.cr0_wp = mask.cr4_pae = mask.nxe = 1;
        for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn, node) {
-               spte = get_written_sptes(sp, gpa, &npte);
-
                if (detect_write_misaligned(sp, gpa, bytes) ||
-                     detect_write_flooding(sp, spte)) {
+                     detect_write_flooding(sp)) {
                        zap_page |= !!kvm_mmu_prepare_zap_page(vcpu->kvm, sp,
                                                     &invalid_list);
                        ++vcpu->kvm->stat.mmu_flooded;
index ea7b4fd34676fe08062e8e76e0825a4170fc17fe..715da5a19a5b6cf8a6abec0a96fddf1d2260cc85 100644 (file)
@@ -200,13 +200,13 @@ static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
        slot = gfn_to_memslot(kvm, sp->gfn);
        rmapp = &slot->rmap[sp->gfn - slot->base_gfn];
 
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                if (is_writable_pte(*spte))
                        audit_printk(kvm, "shadow page has writable "
                                     "mappings: gfn %llx role %x\n",
                                     sp->gfn, sp->role.word);
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
 }
 
index 7aad5446f393def644e685c76dbfcd72e6b2711c..a73f0c1048137062417b43e59785546c38b0dcd5 100644 (file)
@@ -33,10 +33,11 @@ static struct kvm_arch_event_perf_mapping {
        [4] = { 0x2e, 0x41, PERF_COUNT_HW_CACHE_MISSES },
        [5] = { 0xc4, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
        [6] = { 0xc5, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
+       [7] = { 0x00, 0x30, PERF_COUNT_HW_REF_CPU_CYCLES },
 };
 
 /* mapping between fixed pmc index and arch_events array */
-int fixed_pmc_events[] = {1, 0, 2};
+int fixed_pmc_events[] = {1, 0, 7};
 
 static bool pmc_is_gp(struct kvm_pmc *pmc)
 {
@@ -210,6 +211,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
        unsigned config, type = PERF_TYPE_RAW;
        u8 event_select, unit_mask;
 
+       if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
+               printk_once("kvm pmu: pin control bit is ignored\n");
+
        pmc->eventsel = eventsel;
 
        stop_counter(pmc);
@@ -220,7 +224,7 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
        event_select = eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
        unit_mask = (eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
 
-       if (!(event_select & (ARCH_PERFMON_EVENTSEL_EDGE |
+       if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
                                ARCH_PERFMON_EVENTSEL_INV |
                                ARCH_PERFMON_EVENTSEL_CMASK))) {
                config = find_arch_event(&pmc->vcpu->arch.pmu, event_select,
@@ -413,7 +417,7 @@ int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data)
        struct kvm_pmc *counters;
        u64 ctr;
 
-       pmc &= (3u << 30) - 1;
+       pmc &= ~(3u << 30);
        if (!fixed && pmc >= pmu->nr_arch_gp_counters)
                return 1;
        if (fixed && pmc >= pmu->nr_arch_fixed_counters)
index e385214711cbcf005846c1d0e335502a6c7d9709..e334389e1c755eb471c146264e4bf1021ca5333a 100644 (file)
@@ -111,6 +111,12 @@ struct nested_state {
 #define MSRPM_OFFSETS  16
 static u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
 
+/*
+ * Set osvw_len to higher value when updated Revision Guides
+ * are published and we know what the new status bits are
+ */
+static uint64_t osvw_len = 4, osvw_status;
+
 struct vcpu_svm {
        struct kvm_vcpu vcpu;
        struct vmcb *vmcb;
@@ -177,11 +183,13 @@ static bool npt_enabled = true;
 #else
 static bool npt_enabled;
 #endif
-static int npt = 1;
 
+/* allow nested paging (virtualized MMU) for all guests */
+static int npt = true;
 module_param(npt, int, S_IRUGO);
 
-static int nested = 1;
+/* allow nested virtualization in KVM/SVM */
+static int nested = true;
 module_param(nested, int, S_IRUGO);
 
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
@@ -557,6 +565,27 @@ static void svm_init_erratum_383(void)
        erratum_383_found = true;
 }
 
+static void svm_init_osvw(struct kvm_vcpu *vcpu)
+{
+       /*
+        * Guests should see errata 400 and 415 as fixed (assuming that
+        * HLT and IO instructions are intercepted).
+        */
+       vcpu->arch.osvw.length = (osvw_len >= 3) ? (osvw_len) : 3;
+       vcpu->arch.osvw.status = osvw_status & ~(6ULL);
+
+       /*
+        * By increasing VCPU's osvw.length to 3 we are telling the guest that
+        * all osvw.status bits inside that length, including bit 0 (which is
+        * reserved for erratum 298), are valid. However, if host processor's
+        * osvw_len is 0 then osvw_status[0] carries no information. We need to
+        * be conservative here and therefore we tell the guest that erratum 298
+        * is present (because we really don't know).
+        */
+       if (osvw_len == 0 && boot_cpu_data.x86 == 0x10)
+               vcpu->arch.osvw.status |= 1;
+}
+
 static int has_svm(void)
 {
        const char *msg;
@@ -623,6 +652,36 @@ static int svm_hardware_enable(void *garbage)
                __get_cpu_var(current_tsc_ratio) = TSC_RATIO_DEFAULT;
        }
 
+
+       /*
+        * Get OSVW bits.
+        *
+        * Note that it is possible to have a system with mixed processor
+        * revisions and therefore different OSVW bits. If bits are not the same
+        * on different processors then choose the worst case (i.e. if erratum
+        * is present on one processor and not on another then assume that the
+        * erratum is present everywhere).
+        */
+       if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
+               uint64_t len, status = 0;
+               int err;
+
+               len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
+               if (!err)
+                       status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
+                                                     &err);
+
+               if (err)
+                       osvw_status = osvw_len = 0;
+               else {
+                       if (len < osvw_len)
+                               osvw_len = len;
+                       osvw_status |= status;
+                       osvw_status &= (1ULL << osvw_len) - 1;
+               }
+       } else
+               osvw_status = osvw_len = 0;
+
        svm_init_erratum_383();
 
        amd_pmu_enable_virt();
@@ -910,20 +969,25 @@ static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
        return _tsc;
 }
 
-static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
+static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
        u64 ratio;
        u64 khz;
 
-       /* TSC scaling supported? */
-       if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR))
+       /* Guest TSC same frequency as host TSC? */
+       if (!scale) {
+               svm->tsc_ratio = TSC_RATIO_DEFAULT;
                return;
+       }
 
-       /* TSC-Scaling disabled or guest TSC same frequency as host TSC? */
-       if (user_tsc_khz == 0) {
-               vcpu->arch.virtual_tsc_khz = 0;
-               svm->tsc_ratio = TSC_RATIO_DEFAULT;
+       /* TSC scaling supported? */
+       if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
+               if (user_tsc_khz > tsc_khz) {
+                       vcpu->arch.tsc_catchup = 1;
+                       vcpu->arch.tsc_always_catchup = 1;
+               } else
+                       WARN(1, "user requested TSC rate below hardware speed\n");
                return;
        }
 
@@ -938,7 +1002,6 @@ static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
                                user_tsc_khz);
                return;
        }
-       vcpu->arch.virtual_tsc_khz = user_tsc_khz;
        svm->tsc_ratio             = ratio;
 }
 
@@ -958,10 +1021,14 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
-static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
+static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
+       WARN_ON(adjustment < 0);
+       if (host)
+               adjustment = svm_scale_tsc(vcpu, adjustment);
+
        svm->vmcb->control.tsc_offset += adjustment;
        if (is_guest_mode(vcpu))
                svm->nested.hsave->control.tsc_offset += adjustment;
@@ -1191,6 +1258,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
        if (kvm_vcpu_is_bsp(&svm->vcpu))
                svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
 
+       svm_init_osvw(&svm->vcpu);
+
        return &svm->vcpu;
 
 free_page4:
@@ -1268,6 +1337,21 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)
                wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
 
+static void svm_update_cpl(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+       int cpl;
+
+       if (!is_protmode(vcpu))
+               cpl = 0;
+       else if (svm->vmcb->save.rflags & X86_EFLAGS_VM)
+               cpl = 3;
+       else
+               cpl = svm->vmcb->save.cs.selector & 0x3;
+
+       svm->vmcb->save.cpl = cpl;
+}
+
 static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
 {
        return to_svm(vcpu)->vmcb->save.rflags;
@@ -1275,7 +1359,11 @@ static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
 
 static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
 {
+       unsigned long old_rflags = to_svm(vcpu)->vmcb->save.rflags;
+
        to_svm(vcpu)->vmcb->save.rflags = rflags;
+       if ((old_rflags ^ rflags) & X86_EFLAGS_VM)
+               svm_update_cpl(vcpu);
 }
 
 static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
@@ -1543,9 +1631,7 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
                s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
        }
        if (seg == VCPU_SREG_CS)
-               svm->vmcb->save.cpl
-                       = (svm->vmcb->save.cs.attrib
-                          >> SVM_SELECTOR_DPL_SHIFT) & 3;
+               svm_update_cpl(vcpu);
 
        mark_dirty(svm->vmcb, VMCB_SEG);
 }
@@ -2735,7 +2821,10 @@ static int task_switch_interception(struct vcpu_svm *svm)
             (int_vec == OF_VECTOR || int_vec == BP_VECTOR)))
                skip_emulated_instruction(&svm->vcpu);
 
-       if (kvm_task_switch(&svm->vcpu, tss_selector, reason,
+       if (int_type != SVM_EXITINTINFO_TYPE_SOFT)
+               int_vec = -1;
+
+       if (kvm_task_switch(&svm->vcpu, tss_selector, int_vec, reason,
                                has_error_code, error_code) == EMULATE_FAIL) {
                svm->vcpu.run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                svm->vcpu.run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
index 246490f643b64d06940d40e0a6bd3ec0cb431f7f..280751c84724a087ce5a6d9bbeb9c3dba67541bc 100644 (file)
@@ -70,9 +70,6 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 static bool __read_mostly vmm_exclusive = 1;
 module_param(vmm_exclusive, bool, S_IRUGO);
 
-static bool __read_mostly yield_on_hlt = 1;
-module_param(yield_on_hlt, bool, S_IRUGO);
-
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
@@ -1655,17 +1652,6 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
        vmx_set_interrupt_shadow(vcpu, 0);
 }
 
-static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
-{
-       /* Ensure that we clear the HLT state in the VMCS.  We don't need to
-        * explicitly skip the instruction because if the HLT state is set, then
-        * the instruction is already executing and RIP has already been
-        * advanced. */
-       if (!yield_on_hlt &&
-           vmcs_read32(GUEST_ACTIVITY_STATE) == GUEST_ACTIVITY_HLT)
-               vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
-}
-
 /*
  * KVM wants to inject page-faults which it got to the guest. This function
  * checks whether in a nested guest, we need to inject them to L1 or L2.
@@ -1678,7 +1664,7 @@ static int nested_pf_handled(struct kvm_vcpu *vcpu)
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 
        /* TODO: also check PFEC_MATCH/MASK, not just EB.PF. */
-       if (!(vmcs12->exception_bitmap & PF_VECTOR))
+       if (!(vmcs12->exception_bitmap & (1u << PF_VECTOR)))
                return 0;
 
        nested_vmx_vmexit(vcpu);
@@ -1718,7 +1704,6 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
                intr_info |= INTR_TYPE_HARD_EXCEPTION;
 
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
-       vmx_clear_hlt(vcpu);
 }
 
 static bool vmx_rdtscp_supported(void)
@@ -1817,13 +1802,19 @@ u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu)
 }
 
 /*
- * Empty call-back. Needs to be implemented when VMX enables the SET_TSC_KHZ
- * ioctl. In this case the call-back should update internal vmx state to make
- * the changes effective.
+ * Engage any workarounds for mis-matched TSC rates.  Currently limited to
+ * software catchup for faster rates on slower CPUs.
  */
-static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
+static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
 {
-       /* Nothing to do here */
+       if (!scale)
+               return;
+
+       if (user_tsc_khz > tsc_khz) {
+               vcpu->arch.tsc_catchup = 1;
+               vcpu->arch.tsc_always_catchup = 1;
+       } else
+               WARN(1, "user requested TSC rate below hardware speed\n");
 }
 
 /*
@@ -1850,7 +1841,7 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        }
 }
 
-static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
+static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
 {
        u64 offset = vmcs_read64(TSC_OFFSET);
        vmcs_write64(TSC_OFFSET, offset + adjustment);
@@ -2219,6 +2210,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
                        msr->data = data;
+                       if (msr - vmx->guest_msrs < vmx->save_nmsrs)
+                               kvm_set_shared_msr(msr->index, msr->data,
+                                                  msr->mask);
                        break;
                }
                ret = kvm_set_msr_common(vcpu, msr_index, data);
@@ -2399,7 +2393,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                                &_pin_based_exec_control) < 0)
                return -EIO;
 
-       min =
+       min = CPU_BASED_HLT_EXITING |
 #ifdef CONFIG_X86_64
              CPU_BASED_CR8_LOAD_EXITING |
              CPU_BASED_CR8_STORE_EXITING |
@@ -2414,9 +2408,6 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
              CPU_BASED_INVLPG_EXITING |
              CPU_BASED_RDPMC_EXITING;
 
-       if (yield_on_hlt)
-               min |= CPU_BASED_HLT_EXITING;
-
        opt = CPU_BASED_TPR_SHADOW |
              CPU_BASED_USE_MSR_BITMAPS |
              CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
@@ -4003,7 +3994,6 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu)
        } else
                intr |= INTR_TYPE_EXT_INTR;
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
-       vmx_clear_hlt(vcpu);
 }
 
 static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
@@ -4035,7 +4025,6 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
        }
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                        INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
-       vmx_clear_hlt(vcpu);
 }
 
 static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
@@ -4672,9 +4661,10 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
        bool has_error_code = false;
        u32 error_code = 0;
        u16 tss_selector;
-       int reason, type, idt_v;
+       int reason, type, idt_v, idt_index;
 
        idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
        type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
@@ -4712,8 +4702,9 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
                       type != INTR_TYPE_NMI_INTR))
                skip_emulated_instruction(vcpu);
 
-       if (kvm_task_switch(vcpu, tss_selector, reason,
-                               has_error_code, error_code) == EMULATE_FAIL) {
+       if (kvm_task_switch(vcpu, tss_selector,
+                           type == INTR_TYPE_SOFT_INTR ? idt_index : -1, reason,
+                           has_error_code, error_code) == EMULATE_FAIL) {
                vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
                vcpu->run->internal.ndata = 0;
index 54696b5f8443509eb9ed94ab77c9617b46f4407b..4044ce0bf7c1e7741620b8fcda9a78c9cb1bc775 100644 (file)
@@ -97,6 +97,10 @@ EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
 u32  kvm_max_guest_tsc_khz;
 EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz);
 
+/* tsc tolerance in parts per million - default to 1/2 of the NTP threshold */
+static u32 tsc_tolerance_ppm = 250;
+module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
+
 #define KVM_NR_SHARED_MSRS 16
 
 struct kvm_shared_msrs_global {
@@ -969,50 +973,51 @@ static inline u64 get_kernel_ns(void)
 static DEFINE_PER_CPU(unsigned long, cpu_tsc_khz);
 unsigned long max_tsc_khz;
 
-static inline int kvm_tsc_changes_freq(void)
+static inline u64 nsec_to_cycles(struct kvm_vcpu *vcpu, u64 nsec)
 {
-       int cpu = get_cpu();
-       int ret = !boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
-                 cpufreq_quick_get(cpu) != 0;
-       put_cpu();
-       return ret;
+       return pvclock_scale_delta(nsec, vcpu->arch.virtual_tsc_mult,
+                                  vcpu->arch.virtual_tsc_shift);
 }
 
-u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+static u32 adjust_tsc_khz(u32 khz, s32 ppm)
 {
-       if (vcpu->arch.virtual_tsc_khz)
-               return vcpu->arch.virtual_tsc_khz;
-       else
-               return __this_cpu_read(cpu_tsc_khz);
+       u64 v = (u64)khz * (1000000 + ppm);
+       do_div(v, 1000000);
+       return v;
 }
 
-static inline u64 nsec_to_cycles(struct kvm_vcpu *vcpu, u64 nsec)
+static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
 {
-       u64 ret;
-
-       WARN_ON(preemptible());
-       if (kvm_tsc_changes_freq())
-               printk_once(KERN_WARNING
-                "kvm: unreliable cycle conversion on adjustable rate TSC\n");
-       ret = nsec * vcpu_tsc_khz(vcpu);
-       do_div(ret, USEC_PER_SEC);
-       return ret;
-}
+       u32 thresh_lo, thresh_hi;
+       int use_scaling = 0;
 
-static void kvm_init_tsc_catchup(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
-{
        /* Compute a scale to convert nanoseconds in TSC cycles */
        kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000,
-                          &vcpu->arch.tsc_catchup_shift,
-                          &vcpu->arch.tsc_catchup_mult);
+                          &vcpu->arch.virtual_tsc_shift,
+                          &vcpu->arch.virtual_tsc_mult);
+       vcpu->arch.virtual_tsc_khz = this_tsc_khz;
+
+       /*
+        * Compute the variation in TSC rate which is acceptable
+        * within the range of tolerance and decide if the
+        * rate being applied is within that bounds of the hardware
+        * rate.  If so, no scaling or compensation need be done.
+        */
+       thresh_lo = adjust_tsc_khz(tsc_khz, -tsc_tolerance_ppm);
+       thresh_hi = adjust_tsc_khz(tsc_khz, tsc_tolerance_ppm);
+       if (this_tsc_khz < thresh_lo || this_tsc_khz > thresh_hi) {
+               pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", this_tsc_khz, thresh_lo, thresh_hi);
+               use_scaling = 1;
+       }
+       kvm_x86_ops->set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
 }
 
 static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
 {
-       u64 tsc = pvclock_scale_delta(kernel_ns-vcpu->arch.last_tsc_nsec,
-                                     vcpu->arch.tsc_catchup_mult,
-                                     vcpu->arch.tsc_catchup_shift);
-       tsc += vcpu->arch.last_tsc_write;
+       u64 tsc = pvclock_scale_delta(kernel_ns-vcpu->arch.this_tsc_nsec,
+                                     vcpu->arch.virtual_tsc_mult,
+                                     vcpu->arch.virtual_tsc_shift);
+       tsc += vcpu->arch.this_tsc_write;
        return tsc;
 }
 
@@ -1021,48 +1026,88 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
        struct kvm *kvm = vcpu->kvm;
        u64 offset, ns, elapsed;
        unsigned long flags;
-       s64 sdiff;
+       s64 usdiff;
 
        raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
        offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
        ns = get_kernel_ns();
        elapsed = ns - kvm->arch.last_tsc_nsec;
-       sdiff = data - kvm->arch.last_tsc_write;
-       if (sdiff < 0)
-               sdiff = -sdiff;
+
+       /* n.b - signed multiplication and division required */
+       usdiff = data - kvm->arch.last_tsc_write;
+#ifdef CONFIG_X86_64
+       usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz;
+#else
+       /* do_div() only does unsigned */
+       asm("idivl %2; xor %%edx, %%edx"
+           : "=A"(usdiff)
+           : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz));
+#endif
+       do_div(elapsed, 1000);
+       usdiff -= elapsed;
+       if (usdiff < 0)
+               usdiff = -usdiff;
 
        /*
-        * Special case: close write to TSC within 5 seconds of
-        * another CPU is interpreted as an attempt to synchronize
-        * The 5 seconds is to accommodate host load / swapping as
-        * well as any reset of TSC during the boot process.
-        *
-        * In that case, for a reliable TSC, we can match TSC offsets,
-        * or make a best guest using elapsed value.
-        */
-       if (sdiff < nsec_to_cycles(vcpu, 5ULL * NSEC_PER_SEC) &&
-           elapsed < 5ULL * NSEC_PER_SEC) {
+        * Special case: TSC write with a small delta (1 second) of virtual
+        * cycle time against real time is interpreted as an attempt to
+        * synchronize the CPU.
+         *
+        * For a reliable TSC, we can match TSC offsets, and for an unstable
+        * TSC, we add elapsed time in this computation.  We could let the
+        * compensation code attempt to catch up if we fall behind, but
+        * it's better to try to match offsets from the beginning.
+         */
+       if (usdiff < USEC_PER_SEC &&
+           vcpu->arch.virtual_tsc_khz == kvm->arch.last_tsc_khz) {
                if (!check_tsc_unstable()) {
-                       offset = kvm->arch.last_tsc_offset;
+                       offset = kvm->arch.cur_tsc_offset;
                        pr_debug("kvm: matched tsc offset for %llu\n", data);
                } else {
                        u64 delta = nsec_to_cycles(vcpu, elapsed);
-                       offset += delta;
+                       data += delta;
+                       offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
                        pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
                }
-               ns = kvm->arch.last_tsc_nsec;
+       } else {
+               /*
+                * We split periods of matched TSC writes into generations.
+                * For each generation, we track the original measured
+                * nanosecond time, offset, and write, so if TSCs are in
+                * sync, we can match exact offset, and if not, we can match
+                * exact software computaion in compute_guest_tsc()
+                *
+                * These values are tracked in kvm->arch.cur_xxx variables.
+                */
+               kvm->arch.cur_tsc_generation++;
+               kvm->arch.cur_tsc_nsec = ns;
+               kvm->arch.cur_tsc_write = data;
+               kvm->arch.cur_tsc_offset = offset;
+               pr_debug("kvm: new tsc generation %u, clock %llu\n",
+                        kvm->arch.cur_tsc_generation, data);
        }
+
+       /*
+        * We also track th most recent recorded KHZ, write and time to
+        * allow the matching interval to be extended at each write.
+        */
        kvm->arch.last_tsc_nsec = ns;
        kvm->arch.last_tsc_write = data;
-       kvm->arch.last_tsc_offset = offset;
-       kvm_x86_ops->write_tsc_offset(vcpu, offset);
-       raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
+       kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz;
 
        /* Reset of TSC must disable overshoot protection below */
        vcpu->arch.hv_clock.tsc_timestamp = 0;
-       vcpu->arch.last_tsc_write = data;
-       vcpu->arch.last_tsc_nsec = ns;
+       vcpu->arch.last_guest_tsc = data;
+
+       /* Keep track of which generation this VCPU has synchronized to */
+       vcpu->arch.this_tsc_generation = kvm->arch.cur_tsc_generation;
+       vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec;
+       vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write;
+
+       kvm_x86_ops->write_tsc_offset(vcpu, offset);
+       raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 }
+
 EXPORT_SYMBOL_GPL(kvm_write_tsc);
 
 static int kvm_guest_time_update(struct kvm_vcpu *v)
@@ -1078,7 +1123,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        local_irq_save(flags);
        tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
        kernel_ns = get_kernel_ns();
-       this_tsc_khz = vcpu_tsc_khz(v);
+       this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
        if (unlikely(this_tsc_khz == 0)) {
                local_irq_restore(flags);
                kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
@@ -1098,7 +1143,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        if (vcpu->tsc_catchup) {
                u64 tsc = compute_guest_tsc(v, kernel_ns);
                if (tsc > tsc_timestamp) {
-                       kvm_x86_ops->adjust_tsc_offset(v, tsc - tsc_timestamp);
+                       adjust_tsc_offset_guest(v, tsc - tsc_timestamp);
                        tsc_timestamp = tsc;
                }
        }
@@ -1130,7 +1175,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
         * observed by the guest and ensure the new system time is greater.
         */
        max_kernel_ns = 0;
-       if (vcpu->hv_clock.tsc_timestamp && vcpu->last_guest_tsc) {
+       if (vcpu->hv_clock.tsc_timestamp) {
                max_kernel_ns = vcpu->last_guest_tsc -
                                vcpu->hv_clock.tsc_timestamp;
                max_kernel_ns = pvclock_scale_delta(max_kernel_ns,
@@ -1504,6 +1549,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
        case MSR_K7_HWCR:
                data &= ~(u64)0x40;     /* ignore flush filter disable */
                data &= ~(u64)0x100;    /* ignore ignne emulation enable */
+               data &= ~(u64)0x8;      /* ignore TLB cache disable */
                if (data != 0) {
                        pr_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n",
                                data);
@@ -1676,6 +1722,16 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                 */
                pr_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data);
                break;
+       case MSR_AMD64_OSVW_ID_LENGTH:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               vcpu->arch.osvw.length = data;
+               break;
+       case MSR_AMD64_OSVW_STATUS:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               vcpu->arch.osvw.status = data;
+               break;
        default:
                if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr))
                        return xen_hvm_config(vcpu, data);
@@ -1960,6 +2016,16 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
                 */
                data = 0xbe702111;
                break;
+       case MSR_AMD64_OSVW_ID_LENGTH:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               data = vcpu->arch.osvw.length;
+               break;
+       case MSR_AMD64_OSVW_STATUS:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               data = vcpu->arch.osvw.status;
+               break;
        default:
                if (kvm_pmu_msr(vcpu, msr))
                        return kvm_pmu_get_msr(vcpu, msr, pdata);
@@ -2080,6 +2146,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_XSAVE:
        case KVM_CAP_ASYNC_PF:
        case KVM_CAP_GET_TSC_KHZ:
+       case KVM_CAP_PCI_2_3:
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -2214,19 +2281,23 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        }
 
        kvm_x86_ops->vcpu_load(vcpu, cpu);
-       if (unlikely(vcpu->cpu != cpu) || check_tsc_unstable()) {
-               /* Make sure TSC doesn't go backwards */
-               s64 tsc_delta;
-               u64 tsc;
 
-               tsc = kvm_x86_ops->read_l1_tsc(vcpu);
-               tsc_delta = !vcpu->arch.last_guest_tsc ? 0 :
-                            tsc - vcpu->arch.last_guest_tsc;
+       /* Apply any externally detected TSC adjustments (due to suspend) */
+       if (unlikely(vcpu->arch.tsc_offset_adjustment)) {
+               adjust_tsc_offset_host(vcpu, vcpu->arch.tsc_offset_adjustment);
+               vcpu->arch.tsc_offset_adjustment = 0;
+               set_bit(KVM_REQ_CLOCK_UPDATE, &vcpu->requests);
+       }
 
+       if (unlikely(vcpu->cpu != cpu) || check_tsc_unstable()) {
+               s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 :
+                               native_read_tsc() - vcpu->arch.last_host_tsc;
                if (tsc_delta < 0)
                        mark_tsc_unstable("KVM discovered backwards TSC");
                if (check_tsc_unstable()) {
-                       kvm_x86_ops->adjust_tsc_offset(vcpu, -tsc_delta);
+                       u64 offset = kvm_x86_ops->compute_tsc_offset(vcpu,
+                                               vcpu->arch.last_guest_tsc);
+                       kvm_x86_ops->write_tsc_offset(vcpu, offset);
                        vcpu->arch.tsc_catchup = 1;
                }
                kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -2243,7 +2314,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
        kvm_x86_ops->vcpu_put(vcpu);
        kvm_put_guest_fpu(vcpu);
-       vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+       vcpu->arch.last_host_tsc = native_read_tsc();
 }
 
 static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
@@ -2785,26 +2856,21 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                u32 user_tsc_khz;
 
                r = -EINVAL;
-               if (!kvm_has_tsc_control)
-                       break;
-
                user_tsc_khz = (u32)arg;
 
                if (user_tsc_khz >= kvm_max_guest_tsc_khz)
                        goto out;
 
-               kvm_x86_ops->set_tsc_khz(vcpu, user_tsc_khz);
+               if (user_tsc_khz == 0)
+                       user_tsc_khz = tsc_khz;
+
+               kvm_set_tsc_khz(vcpu, user_tsc_khz);
 
                r = 0;
                goto out;
        }
        case KVM_GET_TSC_KHZ: {
-               r = -EIO;
-               if (check_tsc_unstable())
-                       goto out;
-
-               r = vcpu_tsc_khz(vcpu);
-
+               r = vcpu->arch.virtual_tsc_khz;
                goto out;
        }
        default:
@@ -2815,6 +2881,11 @@ out:
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
 static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
 {
        int ret;
@@ -2998,6 +3069,8 @@ static void write_protect_slot(struct kvm *kvm,
                               unsigned long *dirty_bitmap,
                               unsigned long nr_dirty_pages)
 {
+       spin_lock(&kvm->mmu_lock);
+
        /* Not many dirty pages compared to # of shadow pages. */
        if (nr_dirty_pages < kvm->arch.n_used_mmu_pages) {
                unsigned long gfn_offset;
@@ -3005,16 +3078,13 @@ static void write_protect_slot(struct kvm *kvm,
                for_each_set_bit(gfn_offset, dirty_bitmap, memslot->npages) {
                        unsigned long gfn = memslot->base_gfn + gfn_offset;
 
-                       spin_lock(&kvm->mmu_lock);
                        kvm_mmu_rmap_write_protect(kvm, gfn, memslot);
-                       spin_unlock(&kvm->mmu_lock);
                }
                kvm_flush_remote_tlbs(kvm);
-       } else {
-               spin_lock(&kvm->mmu_lock);
+       } else
                kvm_mmu_slot_remove_write_access(kvm, memslot->id);
-               spin_unlock(&kvm->mmu_lock);
-       }
+
+       spin_unlock(&kvm->mmu_lock);
 }
 
 /*
@@ -3133,6 +3203,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = -EEXIST;
                if (kvm->arch.vpic)
                        goto create_irqchip_unlock;
+               r = -EINVAL;
+               if (atomic_read(&kvm->online_vcpus))
+                       goto create_irqchip_unlock;
                r = -ENOMEM;
                vpic = kvm_create_pic(kvm);
                if (vpic) {
@@ -4063,6 +4136,11 @@ static int emulator_set_cr(struct x86_emulate_ctxt *ctxt, int cr, ulong val)
        return res;
 }
 
+static void emulator_set_rflags(struct x86_emulate_ctxt *ctxt, ulong val)
+{
+       kvm_set_rflags(emul_to_vcpu(ctxt), val);
+}
+
 static int emulator_get_cpl(struct x86_emulate_ctxt *ctxt)
 {
        return kvm_x86_ops->get_cpl(emul_to_vcpu(ctxt));
@@ -4244,6 +4322,7 @@ static struct x86_emulate_ops emulate_ops = {
        .set_idt             = emulator_set_idt,
        .get_cr              = emulator_get_cr,
        .set_cr              = emulator_set_cr,
+       .set_rflags          = emulator_set_rflags,
        .cpl                 = emulator_get_cpl,
        .get_dr              = emulator_get_dr,
        .set_dr              = emulator_set_dr,
@@ -5288,6 +5367,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                profile_hit(KVM_PROFILING, (void *)rip);
        }
 
+       if (unlikely(vcpu->arch.tsc_always_catchup))
+               kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 
        kvm_lapic_sync_from_vapic(vcpu);
 
@@ -5587,15 +5668,15 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
-                   bool has_error_code, u32 error_code)
+int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
+                   int reason, bool has_error_code, u32 error_code)
 {
        struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
        int ret;
 
        init_emulate_ctxt(vcpu);
 
-       ret = emulator_task_switch(ctxt, tss_selector, reason,
+       ret = emulator_task_switch(ctxt, tss_selector, idt_index, reason,
                                   has_error_code, error_code);
 
        if (ret)
@@ -5928,13 +6009,88 @@ int kvm_arch_hardware_enable(void *garbage)
        struct kvm *kvm;
        struct kvm_vcpu *vcpu;
        int i;
+       int ret;
+       u64 local_tsc;
+       u64 max_tsc = 0;
+       bool stable, backwards_tsc = false;
 
        kvm_shared_msr_cpu_online();
-       list_for_each_entry(kvm, &vm_list, vm_list)
-               kvm_for_each_vcpu(i, vcpu, kvm)
-                       if (vcpu->cpu == smp_processor_id())
-                               kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
-       return kvm_x86_ops->hardware_enable(garbage);
+       ret = kvm_x86_ops->hardware_enable(garbage);
+       if (ret != 0)
+               return ret;
+
+       local_tsc = native_read_tsc();
+       stable = !check_tsc_unstable();
+       list_for_each_entry(kvm, &vm_list, vm_list) {
+               kvm_for_each_vcpu(i, vcpu, kvm) {
+                       if (!stable && vcpu->cpu == smp_processor_id())
+                               set_bit(KVM_REQ_CLOCK_UPDATE, &vcpu->requests);
+                       if (stable && vcpu->arch.last_host_tsc > local_tsc) {
+                               backwards_tsc = true;
+                               if (vcpu->arch.last_host_tsc > max_tsc)
+                                       max_tsc = vcpu->arch.last_host_tsc;
+                       }
+               }
+       }
+
+       /*
+        * Sometimes, even reliable TSCs go backwards.  This happens on
+        * platforms that reset TSC during suspend or hibernate actions, but
+        * maintain synchronization.  We must compensate.  Fortunately, we can
+        * detect that condition here, which happens early in CPU bringup,
+        * before any KVM threads can be running.  Unfortunately, we can't
+        * bring the TSCs fully up to date with real time, as we aren't yet far
+        * enough into CPU bringup that we know how much real time has actually
+        * elapsed; our helper function, get_kernel_ns() will be using boot
+        * variables that haven't been updated yet.
+        *
+        * So we simply find the maximum observed TSC above, then record the
+        * adjustment to TSC in each VCPU.  When the VCPU later gets loaded,
+        * the adjustment will be applied.  Note that we accumulate
+        * adjustments, in case multiple suspend cycles happen before some VCPU
+        * gets a chance to run again.  In the event that no KVM threads get a
+        * chance to run, we will miss the entire elapsed period, as we'll have
+        * reset last_host_tsc, so VCPUs will not have the TSC adjusted and may
+        * loose cycle time.  This isn't too big a deal, since the loss will be
+        * uniform across all VCPUs (not to mention the scenario is extremely
+        * unlikely). It is possible that a second hibernate recovery happens
+        * much faster than a first, causing the observed TSC here to be
+        * smaller; this would require additional padding adjustment, which is
+        * why we set last_host_tsc to the local tsc observed here.
+        *
+        * N.B. - this code below runs only on platforms with reliable TSC,
+        * as that is the only way backwards_tsc is set above.  Also note
+        * that this runs for ALL vcpus, which is not a bug; all VCPUs should
+        * have the same delta_cyc adjustment applied if backwards_tsc
+        * is detected.  Note further, this adjustment is only done once,
+        * as we reset last_host_tsc on all VCPUs to stop this from being
+        * called multiple times (one for each physical CPU bringup).
+        *
+        * Platforms with unnreliable TSCs don't have to deal with this, they
+        * will be compensated by the logic in vcpu_load, which sets the TSC to
+        * catchup mode.  This will catchup all VCPUs to real time, but cannot
+        * guarantee that they stay in perfect synchronization.
+        */
+       if (backwards_tsc) {
+               u64 delta_cyc = max_tsc - local_tsc;
+               list_for_each_entry(kvm, &vm_list, vm_list) {
+                       kvm_for_each_vcpu(i, vcpu, kvm) {
+                               vcpu->arch.tsc_offset_adjustment += delta_cyc;
+                               vcpu->arch.last_host_tsc = local_tsc;
+                       }
+
+                       /*
+                        * We have to disable TSC offset matching.. if you were
+                        * booting a VM while issuing an S4 host suspend....
+                        * you may have some problem.  Solving this issue is
+                        * left as an exercise to the reader.
+                        */
+                       kvm->arch.last_tsc_nsec = 0;
+                       kvm->arch.last_tsc_write = 0;
+               }
+
+       }
+       return 0;
 }
 
 void kvm_arch_hardware_disable(void *garbage)
@@ -5958,6 +6114,11 @@ void kvm_arch_check_processor_compat(void *rtn)
        kvm_x86_ops->check_processor_compatibility(rtn);
 }
 
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
+{
+       return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
+}
+
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct page *page;
@@ -5980,7 +6141,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        }
        vcpu->arch.pio_data = page_address(page);
 
-       kvm_init_tsc_catchup(vcpu, max_tsc_khz);
+       kvm_set_tsc_khz(vcpu, max_tsc_khz);
 
        r = kvm_mmu_create(vcpu);
        if (r < 0)
@@ -6032,8 +6193,11 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
        free_page((unsigned long)vcpu->arch.pio_data);
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
+       if (type)
+               return -EINVAL;
+
        INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
        INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
@@ -6093,6 +6257,65 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
                put_page(kvm->arch.ept_identity_pagetable);
 }
 
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+       int i;
+
+       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+               if (!dont || free->arch.lpage_info[i] != dont->arch.lpage_info[i]) {
+                       vfree(free->arch.lpage_info[i]);
+                       free->arch.lpage_info[i] = NULL;
+               }
+       }
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       int i;
+
+       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+               unsigned long ugfn;
+               int lpages;
+               int level = i + 2;
+
+               lpages = gfn_to_index(slot->base_gfn + npages - 1,
+                                     slot->base_gfn, level) + 1;
+
+               slot->arch.lpage_info[i] =
+                       vzalloc(lpages * sizeof(*slot->arch.lpage_info[i]));
+               if (!slot->arch.lpage_info[i])
+                       goto out_free;
+
+               if (slot->base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
+                       slot->arch.lpage_info[i][0].write_count = 1;
+               if ((slot->base_gfn + npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
+                       slot->arch.lpage_info[i][lpages - 1].write_count = 1;
+               ugfn = slot->userspace_addr >> PAGE_SHIFT;
+               /*
+                * If the gfn and userspace address are not aligned wrt each
+                * other, or if explicitly asked to, disable large page
+                * support for this slot
+                */
+               if ((slot->base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) ||
+                   !kvm_largepages_enabled()) {
+                       unsigned long j;
+
+                       for (j = 0; j < lpages; ++j)
+                               slot->arch.lpage_info[i][j].write_count = 1;
+               }
+       }
+
+       return 0;
+
+out_free:
+       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+               vfree(slot->arch.lpage_info[i]);
+               slot->arch.lpage_info[i] = NULL;
+       }
+       return -ENOMEM;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                struct kvm_memory_slot *memslot,
                                struct kvm_memory_slot old,
index 7718541541d4ba1143c05f0d2d099686a3d784ff..9b868124128d79699d6325dc579908bc575c3f4a 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/regset.h>
 
 #include <asm/uaccess.h>
+#include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/user.h>
 #include <asm/i387.h>
@@ -269,7 +270,7 @@ void math_emulate(struct math_emu_info *info)
                        FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
 
                        RE_ENTRANT_CHECK_OFF;
-                       current->thread.trap_no = 16;
+                       current->thread.trap_nr = X86_TRAP_MF;
                        current->thread.error_code = 0;
                        send_sig(SIGFPE, current, 1);
                        return;
@@ -662,7 +663,7 @@ static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
 void math_abort(struct math_emu_info *info, unsigned int signal)
 {
        FPU_EIP = FPU_ORIG_EIP;
-       current->thread.trap_no = 16;
+       current->thread.trap_nr = X86_TRAP_MF;
        current->thread.error_code = 0;
        send_sig(signal, current, 1);
        RE_ENTRANT_CHECK_OFF;
index f0b4caf85c1a8687496b863745f11838a4d430b8..3ecfd1aaf214940de7381ecaf456400038ff6fa9 100644 (file)
@@ -615,7 +615,7 @@ pgtable_bad(struct pt_regs *regs, unsigned long error_code,
        dump_pagetable(address);
 
        tsk->thread.cr2         = address;
-       tsk->thread.trap_no     = 14;
+       tsk->thread.trap_nr     = X86_TRAP_PF;
        tsk->thread.error_code  = error_code;
 
        if (__die("Bad pagetable", regs, error_code))
@@ -636,7 +636,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
        /* Are we prepared to handle this kernel fault? */
        if (fixup_exception(regs)) {
                if (current_thread_info()->sig_on_uaccess_error && signal) {
-                       tsk->thread.trap_no = 14;
+                       tsk->thread.trap_nr = X86_TRAP_PF;
                        tsk->thread.error_code = error_code | PF_USER;
                        tsk->thread.cr2 = address;
 
@@ -676,7 +676,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
                printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
 
        tsk->thread.cr2         = address;
-       tsk->thread.trap_no     = 14;
+       tsk->thread.trap_nr     = X86_TRAP_PF;
        tsk->thread.error_code  = error_code;
 
        sig = SIGKILL;
@@ -754,7 +754,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
                /* Kernel addresses are always protection faults: */
                tsk->thread.cr2         = address;
                tsk->thread.error_code  = error_code | (address >= TASK_SIZE);
-               tsk->thread.trap_no     = 14;
+               tsk->thread.trap_nr     = X86_TRAP_PF;
 
                force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0);
 
@@ -838,7 +838,7 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
 
        tsk->thread.cr2         = address;
        tsk->thread.error_code  = error_code;
-       tsk->thread.trap_no     = 14;
+       tsk->thread.trap_nr     = X86_TRAP_PF;
 
 #ifdef CONFIG_MEMORY_FAILURE
        if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
index 6cabf6570d6481c76b34aed0d0f86106fae1f5db..4f0cec7e4ffbc0259937ffd4f5994b76ba8b4a30 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/page_types.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/proto.h>
index 8663f6c47ccbc920c58063633e2d67745448a3d2..575d86f85ce400b2a6798876bd76250bda317828 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/asm.h>
 #include <asm/bios_ebda.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
index 436a0309db332fe54c5a76dbf3952cadd5f16ece..fc18be0f6f29151de06c0a640e2a4e9a67d89ba4 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <asm/processor.h>
 #include <asm/bios_ebda.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index cac7184992567b3c178c41daf7733c6cea69fa3d..a69bcb8c762102d9d778d1dfa3b5635e9eb19793 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
index 1c1c4f46a7c15c19c54923c815556d8c253b847c..efb5b4b93711cec20dd095e0e0a9065a9cc060fb 100644 (file)
@@ -70,7 +70,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
                return;
        pxm = pa->proximity_domain;
        apic_id = pa->apic_id;
-       if (!cpu_has_x2apic && (apic_id >= 0xff)) {
+       if (!apic->apic_id_valid(apic_id)) {
                printk(KERN_INFO "SRAT: PXM %u -> X2APIC 0x%04x ignored\n",
                         pxm, apic_id);
                return;
index bff89dfe36198225f2d7695e5d2ff01ce85e899f..d6aa6e8315d13ac718615947077f2b6fd113cb35 100644 (file)
@@ -67,7 +67,7 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
 {
        struct stack_frame_ia32 *head;
 
-       /* User process is 32-bit */
+       /* User process is IA32 */
        if (!current || !test_thread_flag(TIF_IA32))
                return 0;
 
index e70be38ce03920d4d8210a98ef1038c9ec471745..ce874f872cc6928a96649e441cb01f25bda77a69 100644 (file)
                                        interrupts = <14 1>;
                                };
 
-                               gpio@b,1 {
+                               pcigpio: gpio@b,1 {
+                                       #gpio-cells = <2>;
+                                       #interrupt-cells = <2>;
                                        compatible = "pci8086,2e67.2",
                                                   "pci8086,2e67",
                                                   "pciclassff0000",
                                                   "pciclassff00";
 
-                                       #gpio-cells = <2>;
                                        reg = <0x15900 0x0 0x0 0x0 0x0>;
                                        interrupts = <15 1>;
+                                       interrupt-controller;
                                        gpio-controller;
+                                       intel,muxctl = <0>;
                                };
 
                                i2c-controller@b,2 {
index 246b788847ff727dd7fcca9d120e77ba56fe23a6..5b51194f4c8d1569d57155f134abfd7204efdb48 100644 (file)
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ALIX)             += alix.o
 obj-$(CONFIG_NET5501)          += net5501.o
+obj-$(CONFIG_GEOS)             += geos.o
diff --git a/arch/x86/platform/geode/geos.c b/arch/x86/platform/geode/geos.c
new file mode 100644 (file)
index 0000000..c2e6d53
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * System Specific setup for Traverse Technologies GEOS.
+ * At the moment this means setup of GPIO control of LEDs.
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
+ *                and Philip Prindeville <philipp@redfish-solutions.com>
+ *
+ * TODO: There are large similarities with leds-net5501.c
+ * by Alessandro Zummo <a.zummo@towertech.it>
+ * In the future leds-net5501.c should be migrated over to platform
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/dmi.h>
+
+#include <asm/geode.h>
+
+static struct gpio_keys_button geos_gpio_buttons[] = {
+       {
+               .code = KEY_RESTART,
+               .gpio = 3,
+               .active_low = 1,
+               .desc = "Reset button",
+               .type = EV_KEY,
+               .wakeup = 0,
+               .debounce_interval = 100,
+               .can_disable = 0,
+       }
+};
+static struct gpio_keys_platform_data geos_buttons_data = {
+       .buttons = geos_gpio_buttons,
+       .nbuttons = ARRAY_SIZE(geos_gpio_buttons),
+       .poll_interval = 20,
+};
+
+static struct platform_device geos_buttons_dev = {
+       .name = "gpio-keys-polled",
+       .id = 1,
+       .dev = {
+               .platform_data = &geos_buttons_data,
+       }
+};
+
+static struct gpio_led geos_leds[] = {
+       {
+               .name = "geos:1",
+               .gpio = 6,
+               .default_trigger = "default-on",
+               .active_low = 1,
+       },
+       {
+               .name = "geos:2",
+               .gpio = 25,
+               .default_trigger = "default-off",
+               .active_low = 1,
+       },
+       {
+               .name = "geos:3",
+               .gpio = 27,
+               .default_trigger = "default-off",
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led_platform_data geos_leds_data = {
+       .num_leds = ARRAY_SIZE(geos_leds),
+       .leds = geos_leds,
+};
+
+static struct platform_device geos_leds_dev = {
+       .name = "leds-gpio",
+       .id = -1,
+       .dev.platform_data = &geos_leds_data,
+};
+
+static struct __initdata platform_device *geos_devs[] = {
+       &geos_buttons_dev,
+       &geos_leds_dev,
+};
+
+static void __init register_geos(void)
+{
+       /* Setup LED control through leds-gpio driver */
+       platform_add_devices(geos_devs, ARRAY_SIZE(geos_devs));
+}
+
+static int __init geos_init(void)
+{
+       const char *vendor, *product;
+
+       if (!is_geode())
+               return 0;
+
+       vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+       if (!vendor || strcmp(vendor, "Traverse Technologies"))
+               return 0;
+
+       product = dmi_get_system_info(DMI_PRODUCT_NAME);
+       if (!product || strcmp(product, "Geos"))
+               return 0;
+
+       printk(KERN_INFO "%s: system is recognized as \"%s %s\"\n",
+              KBUILD_MODNAME, vendor, product);
+
+       register_geos();
+
+       return 0;
+}
+
+module_init(geos_init);
+
+MODULE_AUTHOR("Philip Prindeville <philipp@redfish-solutions.com>");
+MODULE_DESCRIPTION("Traverse Technologies Geos System Setup");
+MODULE_LICENSE("GPL");
index 7cce722667b83dd06b506d06b771a572c0843598..a4bee53c2e549a5ff28f6ccd8a85c3abce696ec4 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/syscore_ops.h>
+#include <linux/debugfs.h>
+#include <linux/mutex.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -31,6 +33,15 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
 
 static DEFINE_SPINLOCK(ec_lock);
 
+/* debugfs interface to EC commands */
+#define EC_MAX_CMD_ARGS (5 + 1)        /* cmd byte + 5 args */
+#define EC_MAX_CMD_REPLY (8)
+
+static struct dentry *ec_debugfs_dir;
+static DEFINE_MUTEX(ec_debugfs_cmd_lock);
+static unsigned char ec_debugfs_resp[EC_MAX_CMD_REPLY];
+static unsigned int ec_debugfs_resp_bytes;
+
 /* EC event mask to be applied during suspend (defining wakeup sources). */
 static u16 ec_wakeup_mask;
 
@@ -269,6 +280,91 @@ int olpc_ec_sci_query(u16 *sci_value)
 }
 EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
 
+static ssize_t ec_debugfs_cmd_write(struct file *file, const char __user *buf,
+                                   size_t size, loff_t *ppos)
+{
+       int i, m;
+       unsigned char ec_cmd[EC_MAX_CMD_ARGS];
+       unsigned int ec_cmd_int[EC_MAX_CMD_ARGS];
+       char cmdbuf[64];
+       int ec_cmd_bytes;
+
+       mutex_lock(&ec_debugfs_cmd_lock);
+
+       size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size);
+
+       m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0],
+                  &ec_debugfs_resp_bytes,
+                  &ec_cmd_int[1], &ec_cmd_int[2], &ec_cmd_int[3],
+                  &ec_cmd_int[4], &ec_cmd_int[5]);
+       if (m < 2 || ec_debugfs_resp_bytes > EC_MAX_CMD_REPLY) {
+               /* reset to prevent overflow on read */
+               ec_debugfs_resp_bytes = 0;
+
+               printk(KERN_DEBUG "olpc-ec: bad ec cmd:  "
+                      "cmd:response-count [arg1 [arg2 ...]]\n");
+               size = -EINVAL;
+               goto out;
+       }
+
+       /* convert scanf'd ints to char */
+       ec_cmd_bytes = m - 2;
+       for (i = 0; i <= ec_cmd_bytes; i++)
+               ec_cmd[i] = ec_cmd_int[i];
+
+       printk(KERN_DEBUG "olpc-ec: debugfs cmd 0x%02x with %d args "
+              "%02x %02x %02x %02x %02x, want %d returns\n",
+              ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], ec_cmd[3],
+              ec_cmd[4], ec_cmd[5], ec_debugfs_resp_bytes);
+
+       olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1],
+                   ec_cmd_bytes, ec_debugfs_resp, ec_debugfs_resp_bytes);
+
+       printk(KERN_DEBUG "olpc-ec: response "
+              "%02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n",
+              ec_debugfs_resp[0], ec_debugfs_resp[1], ec_debugfs_resp[2],
+              ec_debugfs_resp[3], ec_debugfs_resp[4], ec_debugfs_resp[5],
+              ec_debugfs_resp[6], ec_debugfs_resp[7], ec_debugfs_resp_bytes);
+
+out:
+       mutex_unlock(&ec_debugfs_cmd_lock);
+       return size;
+}
+
+static ssize_t ec_debugfs_cmd_read(struct file *file, char __user *buf,
+                                  size_t size, loff_t *ppos)
+{
+       unsigned int i, r;
+       char *rp;
+       char respbuf[64];
+
+       mutex_lock(&ec_debugfs_cmd_lock);
+       rp = respbuf;
+       rp += sprintf(rp, "%02x", ec_debugfs_resp[0]);
+       for (i = 1; i < ec_debugfs_resp_bytes; i++)
+               rp += sprintf(rp, ", %02x", ec_debugfs_resp[i]);
+       mutex_unlock(&ec_debugfs_cmd_lock);
+       rp += sprintf(rp, "\n");
+
+       r = rp - respbuf;
+       return simple_read_from_buffer(buf, size, ppos, respbuf, r);
+}
+
+static const struct file_operations ec_debugfs_genops = {
+       .write   = ec_debugfs_cmd_write,
+       .read    = ec_debugfs_cmd_read,
+};
+
+static void setup_debugfs(void)
+{
+       ec_debugfs_dir = debugfs_create_dir("olpc-ec", 0);
+       if (ec_debugfs_dir == ERR_PTR(-ENODEV))
+               return;
+
+       debugfs_create_file("cmd", 0600, ec_debugfs_dir, NULL,
+                           &ec_debugfs_genops);
+}
+
 static int olpc_ec_suspend(void)
 {
        return olpc_ec_mask_write(ec_wakeup_mask);
@@ -372,6 +468,7 @@ static int __init olpc_init(void)
        }
 
        register_syscore_ops(&olpc_syscore_ops);
+       setup_debugfs();
 
        return 0;
 }
index 4889655ba784d49736f29fa42f855edbfabef3ca..47936830968c5240497725557be336f6fed112c9 100644 (file)
@@ -115,7 +115,7 @@ static void __save_processor_state(struct saved_context *ctxt)
 void save_processor_state(void)
 {
        __save_processor_state(&saved_context);
-       save_sched_clock_state();
+       x86_platform.save_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(save_processor_state);
@@ -231,8 +231,8 @@ static void __restore_processor_state(struct saved_context *ctxt)
 /* Needed by apm.c */
 void restore_processor_state(void)
 {
+       x86_platform.restore_sched_clock_state();
        __restore_processor_state(&saved_context);
-       restore_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(restore_processor_state);
index 3769079874d8f57702bbea42bcc7446908b5af23..74202c1910cda6e5d623e99921f85c57420be6f0 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/suspend.h>
 #include <linux/bootmem.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmzone.h>
index 564b2476fede543b46cac645b116110bd4eb8fbb..3236aebc828d45eb7f8761b57d23861e3b46c7ad 100644 (file)
@@ -10,8 +10,10 @@ syshdr := $(srctree)/$(src)/syscallhdr.sh
 systbl := $(srctree)/$(src)/syscalltbl.sh
 
 quiet_cmd_syshdr = SYSHDR  $@
-      cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' $< $@ \
-                  $(syshdr_abi_$(basetarget)) $(syshdr_pfx_$(basetarget))
+      cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \
+                  '$(syshdr_abi_$(basetarget))' \
+                  '$(syshdr_pfx_$(basetarget))' \
+                  '$(syshdr_offset_$(basetarget))'
 quiet_cmd_systbl = SYSTBL  $@
       cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@
 
@@ -24,18 +26,28 @@ syshdr_pfx_unistd_32_ia32 := ia32_
 $(out)/unistd_32_ia32.h: $(syscall32) $(syshdr)
        $(call if_changed,syshdr)
 
-syshdr_abi_unistd_64 := 64
+syshdr_abi_unistd_x32 := common,x32
+syshdr_offset_unistd_x32 := __X32_SYSCALL_BIT
+$(out)/unistd_x32.h: $(syscall64) $(syshdr)
+       $(call if_changed,syshdr)
+
+syshdr_abi_unistd_64 := common,64
 $(out)/unistd_64.h: $(syscall64) $(syshdr)
        $(call if_changed,syshdr)
 
+syshdr_abi_unistd_64_x32 := x32
+syshdr_pfx_unistd_64_x32 := x32_
+$(out)/unistd_64_x32.h: $(syscall64) $(syshdr)
+       $(call if_changed,syshdr)
+
 $(out)/syscalls_32.h: $(syscall32) $(systbl)
        $(call if_changed,systbl)
 $(out)/syscalls_64.h: $(syscall64) $(systbl)
        $(call if_changed,systbl)
 
-syshdr-y                       += unistd_32.h unistd_64.h
+syshdr-y                       += unistd_32.h unistd_64.h unistd_x32.h
 syshdr-y                       += syscalls_32.h
-syshdr-$(CONFIG_X86_64)                += unistd_32_ia32.h
+syshdr-$(CONFIG_X86_64)                += unistd_32_ia32.h unistd_64_x32.h
 syshdr-$(CONFIG_X86_64)                += syscalls_64.h
 
 targets        += $(syshdr-y)
index e7e67cc3c14b82857438b62a85c670e1b31a874c..29f9f0554f7de0244e7120ea69fec26640bf7dce 100644 (file)
 172    i386    prctl                   sys_prctl
 173    i386    rt_sigreturn            ptregs_rt_sigreturn             stub32_rt_sigreturn
 174    i386    rt_sigaction            sys_rt_sigaction                sys32_rt_sigaction
-175    i386    rt_sigprocmask          sys_rt_sigprocmask              sys32_rt_sigprocmask
+175    i386    rt_sigprocmask          sys_rt_sigprocmask
 176    i386    rt_sigpending           sys_rt_sigpending               sys32_rt_sigpending
 177    i386    rt_sigtimedwait         sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait
 178    i386    rt_sigqueueinfo         sys_rt_sigqueueinfo             sys32_rt_sigqueueinfo
index b440a8f7eefa943edc778de428918581c4ff0d0b..dd29a9ea27c560a9d2fcb6e1c2983f8b8e9be407 100644 (file)
 # The format is:
 # <number> <abi> <name> <entry point>
 #
-# The abi is always "64" for this file (for now.)
+# The abi is "common", "64" or "x32" for this file.
 #
-0      64      read                    sys_read
-1      64      write                   sys_write
-2      64      open                    sys_open
-3      64      close                   sys_close
-4      64      stat                    sys_newstat
-5      64      fstat                   sys_newfstat
-6      64      lstat                   sys_newlstat
-7      64      poll                    sys_poll
-8      64      lseek                   sys_lseek
-9      64      mmap                    sys_mmap
-10     64      mprotect                sys_mprotect
-11     64      munmap                  sys_munmap
-12     64      brk                     sys_brk
+0      common  read                    sys_read
+1      common  write                   sys_write
+2      common  open                    sys_open
+3      common  close                   sys_close
+4      common  stat                    sys_newstat
+5      common  fstat                   sys_newfstat
+6      common  lstat                   sys_newlstat
+7      common  poll                    sys_poll
+8      common  lseek                   sys_lseek
+9      common  mmap                    sys_mmap
+10     common  mprotect                sys_mprotect
+11     common  munmap                  sys_munmap
+12     common  brk                     sys_brk
 13     64      rt_sigaction            sys_rt_sigaction
-14     64      rt_sigprocmask          sys_rt_sigprocmask
+14     common  rt_sigprocmask          sys_rt_sigprocmask
 15     64      rt_sigreturn            stub_rt_sigreturn
 16     64      ioctl                   sys_ioctl
-17     64      pread64                 sys_pread64
-18     64      pwrite64                sys_pwrite64
+17     common  pread64                 sys_pread64
+18     common  pwrite64                sys_pwrite64
 19     64      readv                   sys_readv
 20     64      writev                  sys_writev
-21     64      access                  sys_access
-22     64      pipe                    sys_pipe
-23     64      select                  sys_select
-24     64      sched_yield             sys_sched_yield
-25     64      mremap                  sys_mremap
-26     64      msync                   sys_msync
-27     64      mincore                 sys_mincore
-28     64      madvise                 sys_madvise
-29     64      shmget                  sys_shmget
-30     64      shmat                   sys_shmat
-31     64      shmctl                  sys_shmctl
-32     64      dup                     sys_dup
-33     64      dup2                    sys_dup2
-34     64      pause                   sys_pause
-35     64      nanosleep               sys_nanosleep
-36     64      getitimer               sys_getitimer
-37     64      alarm                   sys_alarm
-38     64      setitimer               sys_setitimer
-39     64      getpid                  sys_getpid
-40     64      sendfile                sys_sendfile64
-41     64      socket                  sys_socket
-42     64      connect                 sys_connect
-43     64      accept                  sys_accept
-44     64      sendto                  sys_sendto
+21     common  access                  sys_access
+22     common  pipe                    sys_pipe
+23     common  select                  sys_select
+24     common  sched_yield             sys_sched_yield
+25     common  mremap                  sys_mremap
+26     common  msync                   sys_msync
+27     common  mincore                 sys_mincore
+28     common  madvise                 sys_madvise
+29     common  shmget                  sys_shmget
+30     common  shmat                   sys_shmat
+31     common  shmctl                  sys_shmctl
+32     common  dup                     sys_dup
+33     common  dup2                    sys_dup2
+34     common  pause                   sys_pause
+35     common  nanosleep               sys_nanosleep
+36     common  getitimer               sys_getitimer
+37     common  alarm                   sys_alarm
+38     common  setitimer               sys_setitimer
+39     common  getpid                  sys_getpid
+40     common  sendfile                sys_sendfile64
+41     common  socket                  sys_socket
+42     common  connect                 sys_connect
+43     common  accept                  sys_accept
+44     common  sendto                  sys_sendto
 45     64      recvfrom                sys_recvfrom
 46     64      sendmsg                 sys_sendmsg
 47     64      recvmsg                 sys_recvmsg
-48     64      shutdown                sys_shutdown
-49     64      bind                    sys_bind
-50     64      listen                  sys_listen
-51     64      getsockname             sys_getsockname
-52     64      getpeername             sys_getpeername
-53     64      socketpair              sys_socketpair
-54     64      setsockopt              sys_setsockopt
-55     64      getsockopt              sys_getsockopt
-56     64      clone                   stub_clone
-57     64      fork                    stub_fork
-58     64      vfork                   stub_vfork
+48     common  shutdown                sys_shutdown
+49     common  bind                    sys_bind
+50     common  listen                  sys_listen
+51     common  getsockname             sys_getsockname
+52     common  getpeername             sys_getpeername
+53     common  socketpair              sys_socketpair
+54     common  setsockopt              sys_setsockopt
+55     common  getsockopt              sys_getsockopt
+56     common  clone                   stub_clone
+57     common  fork                    stub_fork
+58     common  vfork                   stub_vfork
 59     64      execve                  stub_execve
-60     64      exit                    sys_exit
-61     64      wait4                   sys_wait4
-62     64      kill                    sys_kill
-63     64      uname                   sys_newuname
-64     64      semget                  sys_semget
-65     64      semop                   sys_semop
-66     64      semctl                  sys_semctl
-67     64      shmdt                   sys_shmdt
-68     64      msgget                  sys_msgget
-69     64      msgsnd                  sys_msgsnd
-70     64      msgrcv                  sys_msgrcv
-71     64      msgctl                  sys_msgctl
-72     64      fcntl                   sys_fcntl
-73     64      flock                   sys_flock
-74     64      fsync                   sys_fsync
-75     64      fdatasync               sys_fdatasync
-76     64      truncate                sys_truncate
-77     64      ftruncate               sys_ftruncate
-78     64      getdents                sys_getdents
-79     64      getcwd                  sys_getcwd
-80     64      chdir                   sys_chdir
-81     64      fchdir                  sys_fchdir
-82     64      rename                  sys_rename
-83     64      mkdir                   sys_mkdir
-84     64      rmdir                   sys_rmdir
-85     64      creat                   sys_creat
-86     64      link                    sys_link
-87     64      unlink                  sys_unlink
-88     64      symlink                 sys_symlink
-89     64      readlink                sys_readlink
-90     64      chmod                   sys_chmod
-91     64      fchmod                  sys_fchmod
-92     64      chown                   sys_chown
-93     64      fchown                  sys_fchown
-94     64      lchown                  sys_lchown
-95     64      umask                   sys_umask
-96     64      gettimeofday            sys_gettimeofday
-97     64      getrlimit               sys_getrlimit
-98     64      getrusage               sys_getrusage
-99     64      sysinfo                 sys_sysinfo
-100    64      times                   sys_times
+60     common  exit                    sys_exit
+61     common  wait4                   sys_wait4
+62     common  kill                    sys_kill
+63     common  uname                   sys_newuname
+64     common  semget                  sys_semget
+65     common  semop                   sys_semop
+66     common  semctl                  sys_semctl
+67     common  shmdt                   sys_shmdt
+68     common  msgget                  sys_msgget
+69     common  msgsnd                  sys_msgsnd
+70     common  msgrcv                  sys_msgrcv
+71     common  msgctl                  sys_msgctl
+72     common  fcntl                   sys_fcntl
+73     common  flock                   sys_flock
+74     common  fsync                   sys_fsync
+75     common  fdatasync               sys_fdatasync
+76     common  truncate                sys_truncate
+77     common  ftruncate               sys_ftruncate
+78     common  getdents                sys_getdents
+79     common  getcwd                  sys_getcwd
+80     common  chdir                   sys_chdir
+81     common  fchdir                  sys_fchdir
+82     common  rename                  sys_rename
+83     common  mkdir                   sys_mkdir
+84     common  rmdir                   sys_rmdir
+85     common  creat                   sys_creat
+86     common  link                    sys_link
+87     common  unlink                  sys_unlink
+88     common  symlink                 sys_symlink
+89     common  readlink                sys_readlink
+90     common  chmod                   sys_chmod
+91     common  fchmod                  sys_fchmod
+92     common  chown                   sys_chown
+93     common  fchown                  sys_fchown
+94     common  lchown                  sys_lchown
+95     common  umask                   sys_umask
+96     common  gettimeofday            sys_gettimeofday
+97     common  getrlimit               sys_getrlimit
+98     common  getrusage               sys_getrusage
+99     common  sysinfo                 sys_sysinfo
+100    common  times                   sys_times
 101    64      ptrace                  sys_ptrace
-102    64      getuid                  sys_getuid
-103    64      syslog                  sys_syslog
-104    64      getgid                  sys_getgid
-105    64      setuid                  sys_setuid
-106    64      setgid                  sys_setgid
-107    64      geteuid                 sys_geteuid
-108    64      getegid                 sys_getegid
-109    64      setpgid                 sys_setpgid
-110    64      getppid                 sys_getppid
-111    64      getpgrp                 sys_getpgrp
-112    64      setsid                  sys_setsid
-113    64      setreuid                sys_setreuid
-114    64      setregid                sys_setregid
-115    64      getgroups               sys_getgroups
-116    64      setgroups               sys_setgroups
-117    64      setresuid               sys_setresuid
-118    64      getresuid               sys_getresuid
-119    64      setresgid               sys_setresgid
-120    64      getresgid               sys_getresgid
-121    64      getpgid                 sys_getpgid
-122    64      setfsuid                sys_setfsuid
-123    64      setfsgid                sys_setfsgid
-124    64      getsid                  sys_getsid
-125    64      capget                  sys_capget
-126    64      capset                  sys_capset
+102    common  getuid                  sys_getuid
+103    common  syslog                  sys_syslog
+104    common  getgid                  sys_getgid
+105    common  setuid                  sys_setuid
+106    common  setgid                  sys_setgid
+107    common  geteuid                 sys_geteuid
+108    common  getegid                 sys_getegid
+109    common  setpgid                 sys_setpgid
+110    common  getppid                 sys_getppid
+111    common  getpgrp                 sys_getpgrp
+112    common  setsid                  sys_setsid
+113    common  setreuid                sys_setreuid
+114    common  setregid                sys_setregid
+115    common  getgroups               sys_getgroups
+116    common  setgroups               sys_setgroups
+117    common  setresuid               sys_setresuid
+118    common  getresuid               sys_getresuid
+119    common  setresgid               sys_setresgid
+120    common  getresgid               sys_getresgid
+121    common  getpgid                 sys_getpgid
+122    common  setfsuid                sys_setfsuid
+123    common  setfsgid                sys_setfsgid
+124    common  getsid                  sys_getsid
+125    common  capget                  sys_capget
+126    common  capset                  sys_capset
 127    64      rt_sigpending           sys_rt_sigpending
 128    64      rt_sigtimedwait         sys_rt_sigtimedwait
 129    64      rt_sigqueueinfo         sys_rt_sigqueueinfo
-130    64      rt_sigsuspend           sys_rt_sigsuspend
+130    common  rt_sigsuspend           sys_rt_sigsuspend
 131    64      sigaltstack             stub_sigaltstack
-132    64      utime                   sys_utime
-133    64      mknod                   sys_mknod
+132    common  utime                   sys_utime
+133    common  mknod                   sys_mknod
 134    64      uselib
-135    64      personality             sys_personality
-136    64      ustat                   sys_ustat
-137    64      statfs                  sys_statfs
-138    64      fstatfs                 sys_fstatfs
-139    64      sysfs                   sys_sysfs
-140    64      getpriority             sys_getpriority
-141    64      setpriority             sys_setpriority
-142    64      sched_setparam          sys_sched_setparam
-143    64      sched_getparam          sys_sched_getparam
-144    64      sched_setscheduler      sys_sched_setscheduler
-145    64      sched_getscheduler      sys_sched_getscheduler
-146    64      sched_get_priority_max  sys_sched_get_priority_max
-147    64      sched_get_priority_min  sys_sched_get_priority_min
-148    64      sched_rr_get_interval   sys_sched_rr_get_interval
-149    64      mlock                   sys_mlock
-150    64      munlock                 sys_munlock
-151    64      mlockall                sys_mlockall
-152    64      munlockall              sys_munlockall
-153    64      vhangup                 sys_vhangup
-154    64      modify_ldt              sys_modify_ldt
-155    64      pivot_root              sys_pivot_root
+135    common  personality             sys_personality
+136    common  ustat                   sys_ustat
+137    common  statfs                  sys_statfs
+138    common  fstatfs                 sys_fstatfs
+139    common  sysfs                   sys_sysfs
+140    common  getpriority             sys_getpriority
+141    common  setpriority             sys_setpriority
+142    common  sched_setparam          sys_sched_setparam
+143    common  sched_getparam          sys_sched_getparam
+144    common  sched_setscheduler      sys_sched_setscheduler
+145    common  sched_getscheduler      sys_sched_getscheduler
+146    common  sched_get_priority_max  sys_sched_get_priority_max
+147    common  sched_get_priority_min  sys_sched_get_priority_min
+148    common  sched_rr_get_interval   sys_sched_rr_get_interval
+149    common  mlock                   sys_mlock
+150    common  munlock                 sys_munlock
+151    common  mlockall                sys_mlockall
+152    common  munlockall              sys_munlockall
+153    common  vhangup                 sys_vhangup
+154    common  modify_ldt              sys_modify_ldt
+155    common  pivot_root              sys_pivot_root
 156    64      _sysctl                 sys_sysctl
-157    64      prctl                   sys_prctl
-158    64      arch_prctl              sys_arch_prctl
-159    64      adjtimex                sys_adjtimex
-160    64      setrlimit               sys_setrlimit
-161    64      chroot                  sys_chroot
-162    64      sync                    sys_sync
-163    64      acct                    sys_acct
-164    64      settimeofday            sys_settimeofday
-165    64      mount                   sys_mount
-166    64      umount2                 sys_umount
-167    64      swapon                  sys_swapon
-168    64      swapoff                 sys_swapoff
-169    64      reboot                  sys_reboot
-170    64      sethostname             sys_sethostname
-171    64      setdomainname           sys_setdomainname
-172    64      iopl                    stub_iopl
-173    64      ioperm                  sys_ioperm
+157    common  prctl                   sys_prctl
+158    common  arch_prctl              sys_arch_prctl
+159    common  adjtimex                sys_adjtimex
+160    common  setrlimit               sys_setrlimit
+161    common  chroot                  sys_chroot
+162    common  sync                    sys_sync
+163    common  acct                    sys_acct
+164    common  settimeofday            sys_settimeofday
+165    common  mount                   sys_mount
+166    common  umount2                 sys_umount
+167    common  swapon                  sys_swapon
+168    common  swapoff                 sys_swapoff
+169    common  reboot                  sys_reboot
+170    common  sethostname             sys_sethostname
+171    common  setdomainname           sys_setdomainname
+172    common  iopl                    stub_iopl
+173    common  ioperm                  sys_ioperm
 174    64      create_module
-175    64      init_module             sys_init_module
-176    64      delete_module           sys_delete_module
+175    common  init_module             sys_init_module
+176    common  delete_module           sys_delete_module
 177    64      get_kernel_syms
 178    64      query_module
-179    64      quotactl                sys_quotactl
+179    common  quotactl                sys_quotactl
 180    64      nfsservctl
-181    64      getpmsg
-182    64      putpmsg
-183    64      afs_syscall
-184    64      tuxcall
-185    64      security
-186    64      gettid                  sys_gettid
-187    64      readahead               sys_readahead
-188    64      setxattr                sys_setxattr
-189    64      lsetxattr               sys_lsetxattr
-190    64      fsetxattr               sys_fsetxattr
-191    64      getxattr                sys_getxattr
-192    64      lgetxattr               sys_lgetxattr
-193    64      fgetxattr               sys_fgetxattr
-194    64      listxattr               sys_listxattr
-195    64      llistxattr              sys_llistxattr
-196    64      flistxattr              sys_flistxattr
-197    64      removexattr             sys_removexattr
-198    64      lremovexattr            sys_lremovexattr
-199    64      fremovexattr            sys_fremovexattr
-200    64      tkill                   sys_tkill
-201    64      time                    sys_time
-202    64      futex                   sys_futex
-203    64      sched_setaffinity       sys_sched_setaffinity
-204    64      sched_getaffinity       sys_sched_getaffinity
+181    common  getpmsg
+182    common  putpmsg
+183    common  afs_syscall
+184    common  tuxcall
+185    common  security
+186    common  gettid                  sys_gettid
+187    common  readahead               sys_readahead
+188    common  setxattr                sys_setxattr
+189    common  lsetxattr               sys_lsetxattr
+190    common  fsetxattr               sys_fsetxattr
+191    common  getxattr                sys_getxattr
+192    common  lgetxattr               sys_lgetxattr
+193    common  fgetxattr               sys_fgetxattr
+194    common  listxattr               sys_listxattr
+195    common  llistxattr              sys_llistxattr
+196    common  flistxattr              sys_flistxattr
+197    common  removexattr             sys_removexattr
+198    common  lremovexattr            sys_lremovexattr
+199    common  fremovexattr            sys_fremovexattr
+200    common  tkill                   sys_tkill
+201    common  time                    sys_time
+202    common  futex                   sys_futex
+203    common  sched_setaffinity       sys_sched_setaffinity
+204    common  sched_getaffinity       sys_sched_getaffinity
 205    64      set_thread_area
-206    64      io_setup                sys_io_setup
-207    64      io_destroy              sys_io_destroy
-208    64      io_getevents            sys_io_getevents
-209    64      io_submit               sys_io_submit
-210    64      io_cancel               sys_io_cancel
+206    common  io_setup                sys_io_setup
+207    common  io_destroy              sys_io_destroy
+208    common  io_getevents            sys_io_getevents
+209    common  io_submit               sys_io_submit
+210    common  io_cancel               sys_io_cancel
 211    64      get_thread_area
-212    64      lookup_dcookie          sys_lookup_dcookie
-213    64      epoll_create            sys_epoll_create
+212    common  lookup_dcookie          sys_lookup_dcookie
+213    common  epoll_create            sys_epoll_create
 214    64      epoll_ctl_old
 215    64      epoll_wait_old
-216    64      remap_file_pages        sys_remap_file_pages
-217    64      getdents64              sys_getdents64
-218    64      set_tid_address         sys_set_tid_address
-219    64      restart_syscall         sys_restart_syscall
-220    64      semtimedop              sys_semtimedop
-221    64      fadvise64               sys_fadvise64
+216    common  remap_file_pages        sys_remap_file_pages
+217    common  getdents64              sys_getdents64
+218    common  set_tid_address         sys_set_tid_address
+219    common  restart_syscall         sys_restart_syscall
+220    common  semtimedop              sys_semtimedop
+221    common  fadvise64               sys_fadvise64
 222    64      timer_create            sys_timer_create
-223    64      timer_settime           sys_timer_settime
-224    64      timer_gettime           sys_timer_gettime
-225    64      timer_getoverrun        sys_timer_getoverrun
-226    64      timer_delete            sys_timer_delete
-227    64      clock_settime           sys_clock_settime
-228    64      clock_gettime           sys_clock_gettime
-229    64      clock_getres            sys_clock_getres
-230    64      clock_nanosleep         sys_clock_nanosleep
-231    64      exit_group              sys_exit_group
-232    64      epoll_wait              sys_epoll_wait
-233    64      epoll_ctl               sys_epoll_ctl
-234    64      tgkill                  sys_tgkill
-235    64      utimes                  sys_utimes
+223    common  timer_settime           sys_timer_settime
+224    common  timer_gettime           sys_timer_gettime
+225    common  timer_getoverrun        sys_timer_getoverrun
+226    common  timer_delete            sys_timer_delete
+227    common  clock_settime           sys_clock_settime
+228    common  clock_gettime           sys_clock_gettime
+229    common  clock_getres            sys_clock_getres
+230    common  clock_nanosleep         sys_clock_nanosleep
+231    common  exit_group              sys_exit_group
+232    common  epoll_wait              sys_epoll_wait
+233    common  epoll_ctl               sys_epoll_ctl
+234    common  tgkill                  sys_tgkill
+235    common  utimes                  sys_utimes
 236    64      vserver
-237    64      mbind                   sys_mbind
-238    64      set_mempolicy           sys_set_mempolicy
-239    64      get_mempolicy           sys_get_mempolicy
-240    64      mq_open                 sys_mq_open
-241    64      mq_unlink               sys_mq_unlink
-242    64      mq_timedsend            sys_mq_timedsend
-243    64      mq_timedreceive         sys_mq_timedreceive
+237    common  mbind                   sys_mbind
+238    common  set_mempolicy           sys_set_mempolicy
+239    common  get_mempolicy           sys_get_mempolicy
+240    common  mq_open                 sys_mq_open
+241    common  mq_unlink               sys_mq_unlink
+242    common  mq_timedsend            sys_mq_timedsend
+243    common  mq_timedreceive         sys_mq_timedreceive
 244    64      mq_notify               sys_mq_notify
-245    64      mq_getsetattr           sys_mq_getsetattr
+245    common  mq_getsetattr           sys_mq_getsetattr
 246    64      kexec_load              sys_kexec_load
 247    64      waitid                  sys_waitid
-248    64      add_key                 sys_add_key
-249    64      request_key             sys_request_key
-250    64      keyctl                  sys_keyctl
-251    64      ioprio_set              sys_ioprio_set
-252    64      ioprio_get              sys_ioprio_get
-253    64      inotify_init            sys_inotify_init
-254    64      inotify_add_watch       sys_inotify_add_watch
-255    64      inotify_rm_watch        sys_inotify_rm_watch
-256    64      migrate_pages           sys_migrate_pages
-257    64      openat                  sys_openat
-258    64      mkdirat                 sys_mkdirat
-259    64      mknodat                 sys_mknodat
-260    64      fchownat                sys_fchownat
-261    64      futimesat               sys_futimesat
-262    64      newfstatat              sys_newfstatat
-263    64      unlinkat                sys_unlinkat
-264    64      renameat                sys_renameat
-265    64      linkat                  sys_linkat
-266    64      symlinkat               sys_symlinkat
-267    64      readlinkat              sys_readlinkat
-268    64      fchmodat                sys_fchmodat
-269    64      faccessat               sys_faccessat
-270    64      pselect6                sys_pselect6
-271    64      ppoll                   sys_ppoll
-272    64      unshare                 sys_unshare
+248    common  add_key                 sys_add_key
+249    common  request_key             sys_request_key
+250    common  keyctl                  sys_keyctl
+251    common  ioprio_set              sys_ioprio_set
+252    common  ioprio_get              sys_ioprio_get
+253    common  inotify_init            sys_inotify_init
+254    common  inotify_add_watch       sys_inotify_add_watch
+255    common  inotify_rm_watch        sys_inotify_rm_watch
+256    common  migrate_pages           sys_migrate_pages
+257    common  openat                  sys_openat
+258    common  mkdirat                 sys_mkdirat
+259    common  mknodat                 sys_mknodat
+260    common  fchownat                sys_fchownat
+261    common  futimesat               sys_futimesat
+262    common  newfstatat              sys_newfstatat
+263    common  unlinkat                sys_unlinkat
+264    common  renameat                sys_renameat
+265    common  linkat                  sys_linkat
+266    common  symlinkat               sys_symlinkat
+267    common  readlinkat              sys_readlinkat
+268    common  fchmodat                sys_fchmodat
+269    common  faccessat               sys_faccessat
+270    common  pselect6                sys_pselect6
+271    common  ppoll                   sys_ppoll
+272    common  unshare                 sys_unshare
 273    64      set_robust_list         sys_set_robust_list
 274    64      get_robust_list         sys_get_robust_list
-275    64      splice                  sys_splice
-276    64      tee                     sys_tee
-277    64      sync_file_range         sys_sync_file_range
+275    common  splice                  sys_splice
+276    common  tee                     sys_tee
+277    common  sync_file_range         sys_sync_file_range
 278    64      vmsplice                sys_vmsplice
 279    64      move_pages              sys_move_pages
-280    64      utimensat               sys_utimensat
-281    64      epoll_pwait             sys_epoll_pwait
-282    64      signalfd                sys_signalfd
-283    64      timerfd_create          sys_timerfd_create
-284    64      eventfd                 sys_eventfd
-285    64      fallocate               sys_fallocate
-286    64      timerfd_settime         sys_timerfd_settime
-287    64      timerfd_gettime         sys_timerfd_gettime
-288    64      accept4                 sys_accept4
-289    64      signalfd4               sys_signalfd4
-290    64      eventfd2                sys_eventfd2
-291    64      epoll_create1           sys_epoll_create1
-292    64      dup3                    sys_dup3
-293    64      pipe2                   sys_pipe2
-294    64      inotify_init1           sys_inotify_init1
+280    common  utimensat               sys_utimensat
+281    common  epoll_pwait             sys_epoll_pwait
+282    common  signalfd                sys_signalfd
+283    common  timerfd_create          sys_timerfd_create
+284    common  eventfd                 sys_eventfd
+285    common  fallocate               sys_fallocate
+286    common  timerfd_settime         sys_timerfd_settime
+287    common  timerfd_gettime         sys_timerfd_gettime
+288    common  accept4                 sys_accept4
+289    common  signalfd4               sys_signalfd4
+290    common  eventfd2                sys_eventfd2
+291    common  epoll_create1           sys_epoll_create1
+292    common  dup3                    sys_dup3
+293    common  pipe2                   sys_pipe2
+294    common  inotify_init1           sys_inotify_init1
 295    64      preadv                  sys_preadv
 296    64      pwritev                 sys_pwritev
 297    64      rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo
-298    64      perf_event_open         sys_perf_event_open
+298    common  perf_event_open         sys_perf_event_open
 299    64      recvmmsg                sys_recvmmsg
-300    64      fanotify_init           sys_fanotify_init
-301    64      fanotify_mark           sys_fanotify_mark
-302    64      prlimit64               sys_prlimit64
-303    64      name_to_handle_at       sys_name_to_handle_at
-304    64      open_by_handle_at       sys_open_by_handle_at
-305    64      clock_adjtime           sys_clock_adjtime
-306    64      syncfs                  sys_syncfs
+300    common  fanotify_init           sys_fanotify_init
+301    common  fanotify_mark           sys_fanotify_mark
+302    common  prlimit64               sys_prlimit64
+303    common  name_to_handle_at       sys_name_to_handle_at
+304    common  open_by_handle_at       sys_open_by_handle_at
+305    common  clock_adjtime           sys_clock_adjtime
+306    common  syncfs                  sys_syncfs
 307    64      sendmmsg                sys_sendmmsg
-308    64      setns                   sys_setns
-309    64      getcpu                  sys_getcpu
+308    common  setns                   sys_setns
+309    common  getcpu                  sys_getcpu
 310    64      process_vm_readv        sys_process_vm_readv
 311    64      process_vm_writev       sys_process_vm_writev
+#
+# x32-specific system call numbers start at 512 to avoid cache impact
+# for native 64-bit operation.
+#
+512    x32     rt_sigaction            sys32_rt_sigaction
+513    x32     rt_sigreturn            stub_x32_rt_sigreturn
+514    x32     ioctl                   compat_sys_ioctl
+515    x32     readv                   compat_sys_readv
+516    x32     writev                  compat_sys_writev
+517    x32     recvfrom                compat_sys_recvfrom
+518    x32     sendmsg                 compat_sys_sendmsg
+519    x32     recvmsg                 compat_sys_recvmsg
+520    x32     execve                  stub_x32_execve
+521    x32     ptrace                  compat_sys_ptrace
+522    x32     rt_sigpending           sys32_rt_sigpending
+523    x32     rt_sigtimedwait         compat_sys_rt_sigtimedwait
+524    x32     rt_sigqueueinfo         sys32_rt_sigqueueinfo
+525    x32     sigaltstack             stub_x32_sigaltstack
+526    x32     timer_create            compat_sys_timer_create
+527    x32     mq_notify               compat_sys_mq_notify
+528    x32     kexec_load              compat_sys_kexec_load
+529    x32     waitid                  compat_sys_waitid
+530    x32     set_robust_list         compat_sys_set_robust_list
+531    x32     get_robust_list         compat_sys_get_robust_list
+532    x32     vmsplice                compat_sys_vmsplice
+533    x32     move_pages              compat_sys_move_pages
+534    x32     preadv                  compat_sys_preadv64
+535    x32     pwritev                 compat_sys_pwritev64
+536    x32     rt_tgsigqueueinfo       compat_sys_rt_tgsigqueueinfo
+537    x32     recvmmsg                compat_sys_recvmmsg
+538    x32     sendmmsg                compat_sys_sendmmsg
+539    x32     process_vm_readv        compat_sys_process_vm_readv
+540    x32     process_vm_writev       compat_sys_process_vm_writev
index fe626c3ba01b280a6ddc9b2bc3fb894b7c504c3e..9924776f42650476eac999666fcc29b09ccb9a28 100644 (file)
@@ -35,6 +35,9 @@
 #define stub_sigaltstack sys_sigaltstack
 #define stub_rt_sigreturn sys_rt_sigreturn
 
+#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
+#define __SYSCALL_X32(nr, sym, compat) /* Not supported */
+
 #define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ;
 #include <asm/syscalls_64.h>
 
index 5edf4f4bbf531f2e3912a1068bf78f65de8cbcf8..ce7e3607a870feac770b277970b74099c3049208 100644 (file)
@@ -15,6 +15,8 @@ static char syscalls[] = {
 };
 #else
 #define __SYSCALL_64(nr, sym, compat) [nr] = 1,
+#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1,
+#define __SYSCALL_X32(nr, sym, compat) /* Not supported */
 static char syscalls[] = {
 #include <asm/syscalls_64.h>
 };
index 60274d5746e1020ff24c648c68e0bfbb70e66c59..3282874bc61dd11bce83fd65687edff744dacf6c 100644 (file)
@@ -1,5 +1,7 @@
 vdso.lds
 vdso-syms.lds
+vdsox32.lds
+vdsox32-syms.lds
 vdso32-syms.lds
 vdso32-syscall-syms.lds
 vdso32-sysenter-syms.lds
index 5d179502a52cce8ee6b9f8f5fe643a35e0bf472a..fd14be1d1472204afc041a5bef320b2f7c7275af 100644 (file)
@@ -3,21 +3,29 @@
 #
 
 VDSO64-$(CONFIG_X86_64)                := y
+VDSOX32-$(CONFIG_X86_X32_ABI)  := y
 VDSO32-$(CONFIG_X86_32)                := y
 VDSO32-$(CONFIG_COMPAT)                := y
 
 vdso-install-$(VDSO64-y)       += vdso.so
+vdso-install-$(VDSOX32-y)      += vdsox32.so
 vdso-install-$(VDSO32-y)       += $(vdso32-images)
 
 
 # files to link into the vdso
 vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
 
+vobjs-$(VDSOX32-y) += $(vobjx32s-compat)
+
+# Filter out x32 objects.
+vobj64s := $(filter-out $(vobjx32s-compat),$(vobjs-y))
+
 # files to link into kernel
 obj-$(VDSO64-y)                        += vma.o vdso.o
+obj-$(VDSOX32-y)               += vdsox32.o
 obj-$(VDSO32-y)                        += vdso32.o vdso32-setup.o
 
-vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+vobjs := $(foreach F,$(vobj64s),$(obj)/$F)
 
 $(obj)/vdso.o: $(obj)/vdso.so
 
@@ -72,6 +80,42 @@ endef
 $(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
        $(call if_changed,vdsosym)
 
+#
+# X32 processes use x32 vDSO to access 64bit kernel data.
+#
+# Build x32 vDSO image:
+# 1. Compile x32 vDSO as 64bit.
+# 2. Convert object files to x32.
+# 3. Build x32 VDSO image with x32 objects, which contains 64bit codes
+# so that it can reach 64bit address space with 64bit pointers.
+#
+
+targets += vdsox32-syms.lds
+obj-$(VDSOX32-y)               += vdsox32-syms.lds
+
+CPPFLAGS_vdsox32.lds = $(CPPFLAGS_vdso.lds)
+VDSO_LDFLAGS_vdsox32.lds = -Wl,-m,elf32_x86_64 \
+                          -Wl,-soname=linux-vdso.so.1 \
+                          -Wl,-z,max-page-size=4096 \
+                          -Wl,-z,common-page-size=4096
+
+vobjx32s-y := $(vobj64s:.o=-x32.o)
+vobjx32s := $(foreach F,$(vobjx32s-y),$(obj)/$F)
+
+# Convert 64bit object file to x32 for x32 vDSO.
+quiet_cmd_x32 = X32     $@
+      cmd_x32 = $(OBJCOPY) -O elf32-x86-64 $< $@
+
+$(obj)/%-x32.o: $(obj)/%.o FORCE
+       $(call if_changed,x32)
+
+targets += vdsox32.so vdsox32.so.dbg vdsox32.lds $(vobjx32s-y)
+
+$(obj)/vdsox32.o: $(src)/vdsox32.S $(obj)/vdsox32.so
+
+$(obj)/vdsox32.so.dbg: $(src)/vdsox32.lds $(vobjx32s) FORCE
+       $(call if_changed,vdso)
+
 #
 # Build multiple 32-bit vDSO images to choose from at boot time.
 #
index 6bc0e723b6e88bed3ff4bdcee9bc5d96d5377ea8..885eff49d6abe61c2bdfc3c6673acb69678f161b 100644 (file)
@@ -70,100 +70,98 @@ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
        return ret;
 }
 
+notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz)
+{
+       long ret;
+
+       asm("syscall" : "=a" (ret) :
+           "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+       return ret;
+}
+
+
 notrace static inline long vgetns(void)
 {
        long v;
        cycles_t cycles;
        if (gtod->clock.vclock_mode == VCLOCK_TSC)
                cycles = vread_tsc();
-       else
+       else if (gtod->clock.vclock_mode == VCLOCK_HPET)
                cycles = vread_hpet();
+       else
+               return 0;
        v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
        return (v * gtod->clock.mult) >> gtod->clock.shift;
 }
 
-notrace static noinline int do_realtime(struct timespec *ts)
+/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
+notrace static int __always_inline do_realtime(struct timespec *ts)
 {
        unsigned long seq, ns;
+       int mode;
+
        do {
-               seq = read_seqbegin(&gtod->lock);
+               seq = read_seqcount_begin(&gtod->seq);
+               mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ts->tv_nsec = gtod->wall_time_nsec;
                ns = vgetns();
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
+
        timespec_add_ns(ts, ns);
-       return 0;
+       return mode;
 }
 
-notrace static noinline int do_monotonic(struct timespec *ts)
+notrace static int do_monotonic(struct timespec *ts)
 {
-       unsigned long seq, ns, secs;
+       unsigned long seq, ns;
+       int mode;
+
        do {
-               seq = read_seqbegin(&gtod->lock);
-               secs = gtod->wall_time_sec;
-               ns = gtod->wall_time_nsec + vgetns();
-               secs += gtod->wall_to_monotonic.tv_sec;
-               ns += gtod->wall_to_monotonic.tv_nsec;
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
-
-       /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec
-        * are all guaranteed to be nonnegative.
-        */
-       while (ns >= NSEC_PER_SEC) {
-               ns -= NSEC_PER_SEC;
-               ++secs;
-       }
-       ts->tv_sec = secs;
-       ts->tv_nsec = ns;
+               seq = read_seqcount_begin(&gtod->seq);
+               mode = gtod->clock.vclock_mode;
+               ts->tv_sec = gtod->monotonic_time_sec;
+               ts->tv_nsec = gtod->monotonic_time_nsec;
+               ns = vgetns();
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
+       timespec_add_ns(ts, ns);
 
-       return 0;
+       return mode;
 }
 
-notrace static noinline int do_realtime_coarse(struct timespec *ts)
+notrace static int do_realtime_coarse(struct timespec *ts)
 {
        unsigned long seq;
        do {
-               seq = read_seqbegin(&gtod->lock);
+               seq = read_seqcount_begin(&gtod->seq);
                ts->tv_sec = gtod->wall_time_coarse.tv_sec;
                ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
        return 0;
 }
 
-notrace static noinline int do_monotonic_coarse(struct timespec *ts)
+notrace static int do_monotonic_coarse(struct timespec *ts)
 {
-       unsigned long seq, ns, secs;
+       unsigned long seq;
        do {
-               seq = read_seqbegin(&gtod->lock);
-               secs = gtod->wall_time_coarse.tv_sec;
-               ns = gtod->wall_time_coarse.tv_nsec;
-               secs += gtod->wall_to_monotonic.tv_sec;
-               ns += gtod->wall_to_monotonic.tv_nsec;
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
-
-       /* wall_time_nsec and wall_to_monotonic.tv_nsec are
-        * guaranteed to be between 0 and NSEC_PER_SEC.
-        */
-       if (ns >= NSEC_PER_SEC) {
-               ns -= NSEC_PER_SEC;
-               ++secs;
-       }
-       ts->tv_sec = secs;
-       ts->tv_nsec = ns;
+               seq = read_seqcount_begin(&gtod->seq);
+               ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
+               ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
        return 0;
 }
 
 notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
 {
+       int ret = VCLOCK_NONE;
+
        switch (clock) {
        case CLOCK_REALTIME:
-               if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
-                       return do_realtime(ts);
+               ret = do_realtime(ts);
                break;
        case CLOCK_MONOTONIC:
-               if (likely(gtod->clock.vclock_mode != VCLOCK_NONE))
-                       return do_monotonic(ts);
+               ret = do_monotonic(ts);
                break;
        case CLOCK_REALTIME_COARSE:
                return do_realtime_coarse(ts);
@@ -171,32 +169,33 @@ notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
                return do_monotonic_coarse(ts);
        }
 
-       return vdso_fallback_gettime(clock, ts);
+       if (ret == VCLOCK_NONE)
+               return vdso_fallback_gettime(clock, ts);
+       return 0;
 }
 int clock_gettime(clockid_t, struct timespec *)
        __attribute__((weak, alias("__vdso_clock_gettime")));
 
 notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
 {
-       long ret;
-       if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) {
-               if (likely(tv != NULL)) {
-                       BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
-                                    offsetof(struct timespec, tv_nsec) ||
-                                    sizeof(*tv) != sizeof(struct timespec));
-                       do_realtime((struct timespec *)tv);
-                       tv->tv_usec /= 1000;
-               }
-               if (unlikely(tz != NULL)) {
-                       /* Avoid memcpy. Some old compilers fail to inline it */
-                       tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest;
-                       tz->tz_dsttime = gtod->sys_tz.tz_dsttime;
-               }
-               return 0;
+       long ret = VCLOCK_NONE;
+
+       if (likely(tv != NULL)) {
+               BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+                            offsetof(struct timespec, tv_nsec) ||
+                            sizeof(*tv) != sizeof(struct timespec));
+               ret = do_realtime((struct timespec *)tv);
+               tv->tv_usec /= 1000;
        }
-       asm("syscall" : "=a" (ret) :
-           "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
-       return ret;
+       if (unlikely(tz != NULL)) {
+               /* Avoid memcpy. Some old compilers fail to inline it */
+               tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest;
+               tz->tz_dsttime = gtod->sys_tz.tz_dsttime;
+       }
+
+       if (ret == VCLOCK_NONE)
+               return vdso_fallback_gtod(tv, tz);
+       return 0;
 }
 int gettimeofday(struct timeval *, struct timezone *)
        __attribute__((weak, alias("__vdso_gettimeofday")));
index a944020fa8593f634b3c81ad28d26c6c1de1241b..66e6d93598262a2877666f1d1163125207f9c89a 100644 (file)
@@ -311,6 +311,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
        int ret = 0;
        bool compat;
 
+#ifdef CONFIG_X86_X32_ABI
+       if (test_thread_flag(TIF_X32))
+               return x32_setup_additional_pages(bprm, uses_interp);
+#endif
+
        if (vdso_enabled == VDSO_DISABLED)
                return 0;
 
diff --git a/arch/x86/vdso/vdsox32.S b/arch/x86/vdso/vdsox32.S
new file mode 100644 (file)
index 0000000..d6b9a7f
--- /dev/null
@@ -0,0 +1,22 @@
+#include <asm/page_types.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+__PAGE_ALIGNED_DATA
+
+       .globl vdsox32_start, vdsox32_end
+       .align PAGE_SIZE
+vdsox32_start:
+       .incbin "arch/x86/vdso/vdsox32.so"
+vdsox32_end:
+       .align PAGE_SIZE /* extra data here leaks to userspace. */
+
+.previous
+
+       .globl vdsox32_pages
+       .bss
+       .align 8
+       .type vdsox32_pages, @object
+vdsox32_pages:
+       .zero (vdsox32_end - vdsox32_start + PAGE_SIZE - 1) / PAGE_SIZE * 8
+       .size vdsox32_pages, .-vdsox32_pages
diff --git a/arch/x86/vdso/vdsox32.lds.S b/arch/x86/vdso/vdsox32.lds.S
new file mode 100644 (file)
index 0000000..62272aa
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Linker script for x32 vDSO.
+ * We #include the file to define the layout details.
+ * Here we only choose the prelinked virtual address.
+ *
+ * This file defines the version script giving the user-exported symbols in
+ * the DSO.  We can define local symbols here called VDSO* to make their
+ * values visible using the asm-x86/vdso.h macros from the kernel proper.
+ */
+
+#define VDSO_PRELINK 0
+#include "vdso-layout.lds.S"
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION {
+       LINUX_2.6 {
+       global:
+               __vdso_clock_gettime;
+               __vdso_gettimeofday;
+               __vdso_getcpu;
+               __vdso_time;
+       local: *;
+       };
+}
+
+VDSOX32_PRELINK = VDSO_PRELINK;
index 17e18279649f7029d7c2b10881ad155e6a022e00..00aaf047b39f9ac948e0fdd3ccdbf1e4d80e9fb7 100644 (file)
@@ -24,7 +24,44 @@ extern unsigned short vdso_sync_cpuid;
 extern struct page *vdso_pages[];
 static unsigned vdso_size;
 
-static void __init patch_vdso(void *vdso, size_t len)
+#ifdef CONFIG_X86_X32_ABI
+extern char vdsox32_start[], vdsox32_end[];
+extern struct page *vdsox32_pages[];
+static unsigned vdsox32_size;
+
+static void __init patch_vdsox32(void *vdso, size_t len)
+{
+       Elf32_Ehdr *hdr = vdso;
+       Elf32_Shdr *sechdrs, *alt_sec = 0;
+       char *secstrings;
+       void *alt_data;
+       int i;
+
+       BUG_ON(len < sizeof(Elf32_Ehdr));
+       BUG_ON(memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0);
+
+       sechdrs = (void *)hdr + hdr->e_shoff;
+       secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+       for (i = 1; i < hdr->e_shnum; i++) {
+               Elf32_Shdr *shdr = &sechdrs[i];
+               if (!strcmp(secstrings + shdr->sh_name, ".altinstructions")) {
+                       alt_sec = shdr;
+                       goto found;
+               }
+       }
+
+       /* If we get here, it's probably a bug. */
+       pr_warning("patch_vdsox32: .altinstructions not found\n");
+       return;  /* nothing to patch */
+
+found:
+       alt_data = (void *)hdr + alt_sec->sh_offset;
+       apply_alternatives(alt_data, alt_data + alt_sec->sh_size);
+}
+#endif
+
+static void __init patch_vdso64(void *vdso, size_t len)
 {
        Elf64_Ehdr *hdr = vdso;
        Elf64_Shdr *sechdrs, *alt_sec = 0;
@@ -47,7 +84,7 @@ static void __init patch_vdso(void *vdso, size_t len)
        }
 
        /* If we get here, it's probably a bug. */
-       pr_warning("patch_vdso: .altinstructions not found\n");
+       pr_warning("patch_vdso64: .altinstructions not found\n");
        return;  /* nothing to patch */
 
 found:
@@ -60,12 +97,20 @@ static int __init init_vdso(void)
        int npages = (vdso_end - vdso_start + PAGE_SIZE - 1) / PAGE_SIZE;
        int i;
 
-       patch_vdso(vdso_start, vdso_end - vdso_start);
+       patch_vdso64(vdso_start, vdso_end - vdso_start);
 
        vdso_size = npages << PAGE_SHIFT;
        for (i = 0; i < npages; i++)
                vdso_pages[i] = virt_to_page(vdso_start + i*PAGE_SIZE);
 
+#ifdef CONFIG_X86_X32_ABI
+       patch_vdsox32(vdsox32_start, vdsox32_end - vdsox32_start);
+       npages = (vdsox32_end - vdsox32_start + PAGE_SIZE - 1) / PAGE_SIZE;
+       vdsox32_size = npages << PAGE_SHIFT;
+       for (i = 0; i < npages; i++)
+               vdsox32_pages[i] = virt_to_page(vdsox32_start + i*PAGE_SIZE);
+#endif
+
        return 0;
 }
 subsys_initcall(init_vdso);
@@ -103,7 +148,10 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
 
 /* Setup a VMA at program startup for the vsyscall page.
    Not called for compat tasks */
-int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+static int setup_additional_pages(struct linux_binprm *bprm,
+                                 int uses_interp,
+                                 struct page **pages,
+                                 unsigned size)
 {
        struct mm_struct *mm = current->mm;
        unsigned long addr;
@@ -113,8 +161,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
                return 0;
 
        down_write(&mm->mmap_sem);
-       addr = vdso_addr(mm->start_stack, vdso_size);
-       addr = get_unmapped_area(NULL, addr, vdso_size, 0, 0);
+       addr = vdso_addr(mm->start_stack, size);
+       addr = get_unmapped_area(NULL, addr, size, 0, 0);
        if (IS_ERR_VALUE(addr)) {
                ret = addr;
                goto up_fail;
@@ -122,10 +170,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        current->mm->context.vdso = (void *)addr;
 
-       ret = install_special_mapping(mm, addr, vdso_size,
+       ret = install_special_mapping(mm, addr, size,
                                      VM_READ|VM_EXEC|
                                      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-                                     vdso_pages);
+                                     pages);
        if (ret) {
                current->mm->context.vdso = NULL;
                goto up_fail;
@@ -136,6 +184,20 @@ up_fail:
        return ret;
 }
 
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+       return setup_additional_pages(bprm, uses_interp, vdso_pages,
+                                     vdso_size);
+}
+
+#ifdef CONFIG_X86_X32_ABI
+int x32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+       return setup_additional_pages(bprm, uses_interp, vdsox32_pages,
+                                     vdsox32_size);
+}
+#endif
+
 static __init int vdso_setup(char *s)
 {
        vdso_enabled = simple_strtoul(s, NULL, 0);
index f932b30b47fb3fe3f868c18d80e03db0e4bcc424..ddab37b24741f03e901d2078911d4c576734f06d 100644 (file)
@@ -113,7 +113,7 @@ CONFIG_DEFAULT_IOSCHED="noop"
 # CONFIG_INLINE_SPIN_LOCK_BH is not set
 # CONFIG_INLINE_SPIN_LOCK_IRQ is not set
 # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
-CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_UNINLINE_SPIN_UNLOCK is not set
 # CONFIG_INLINE_SPIN_UNLOCK_BH is not set
 CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
 # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
index 23592eff67add99a13cdcf3f27dd1e8947c98e79..b4098930877587d7dec309bbc702a5ed674c94f6 100644 (file)
@@ -18,7 +18,7 @@
 
 #ifdef __KERNEL__
 #include <asm/processor.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i) { (i) }
 
diff --git a/arch/xtensa/include/asm/barrier.h b/arch/xtensa/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..55707a8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SYSTEM_H
+#define _XTENSA_SYSTEM_H
+
+#define smp_read_barrier_depends() do { } while(0)
+#define read_barrier_depends() do { } while(0)
+
+#define mb()  barrier()
+#define rmb() mb()
+#define wmb() mb()
+
+#ifdef CONFIG_SMP
+#error smp_* not defined
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#endif
+
+#define set_mb(var, value)     do { var = value; mb(); } while (0)
+
+#endif /* _XTENSA_SYSTEM_H */
index 40aa7fe77f668464450126184297e22aac51410d..5270197ddd369bd76771ab1f05a2c5bbb24563cb 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/processor.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_SMP
 # error SMP not supported on this architecture
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..e321490
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Atomic xchg and cmpxchg operations.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CMPXCHG_H
+#define _XTENSA_CMPXCHG_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/stringify.h>
+
+/*
+ * cmpxchg
+ */
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *p, int old, int new)
+{
+  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+                      "l32i    %0, %1, 0              \n\t"
+                      "bne     %0, %2, 1f             \n\t"
+                      "s32i    %3, %1, 0              \n\t"
+                      "1:                             \n\t"
+                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "rsync                          \n\t"
+                      : "=&a" (old)
+                      : "a" (p), "a" (old), "r" (new)
+                      : "a15", "memory");
+  return old;
+}
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+       case 4:  return __cmpxchg_u32(ptr, old, new);
+       default: __cmpxchg_called_with_bad_pointer();
+                return old;
+       }
+}
+
+#define cmpxchg(ptr,o,n)                                                     \
+       ({ __typeof__(*(ptr)) _o_ = (o);                                      \
+          __typeof__(*(ptr)) _n_ = (n);                                      \
+          (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                       (unsigned long)_n_, sizeof (*(ptr))); \
+       })
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+/*
+ * xchg_u32
+ *
+ * Note that a15 is used here because the register allocation
+ * done by the compiler is not guaranteed and a window overflow
+ * may not occur between the rsil and wsr instructions. By using
+ * a15 in the rsil, the machine is guaranteed to be in a state
+ * where no register reference will cause an overflow.
+ */
+
+static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
+{
+  unsigned long tmp;
+  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+                      "l32i    %0, %1, 0              \n\t"
+                      "s32i    %2, %1, 0              \n\t"
+                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "rsync                          \n\t"
+                      : "=&a" (tmp)
+                      : "a" (m), "a" (val)
+                      : "a15", "memory");
+  return tmp;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/*
+ * This only works if the compiler isn't horribly bad at optimizing.
+ * gcc-2.5.8 reportedly can't handle this, but I define that one to
+ * be dead anyway.
+ */
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+               case 4:
+                       return xchg_u32(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _XTENSA_CMPXCHG_H */
diff --git a/arch/xtensa/include/asm/exec.h b/arch/xtensa/include/asm/exec.h
new file mode 100644 (file)
index 0000000..af949e2
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_EXEC_H
+#define _XTENSA_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _XTENSA_EXEC_H */
index 6b2190c3588287446e66edd4bdf1803c17d298f1..6e96be0d02d382dd26d68b5774e74f1b914fbd4d 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_ino_t;
-typedef unsigned int   __kernel_mode_t;
-typedef unsigned long  __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
 typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
 typedef unsigned int   __kernel_size_t;
 typedef int            __kernel_ssize_t;
 typedef long           __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char *         __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
+#define __kernel_size_t __kernel_size_t
 
 typedef unsigned short __kernel_old_uid_t;
 typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#ifndef __GNUC__
-
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
-#define        __FD_ZERO(set)  \
-  ((void) memset ((void *) (set), 0, sizeof (__kernel_fd_set)))
-
-#else /* __GNUC__ */
+#define __kernel_old_uid_t __kernel_old_uid_t
 
-#if defined(__KERNEL__)
-/* With GNU C, use inline functions instead so args are evaluated only once: */
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
-{
-       unsigned long _tmp = fd / __NFDBITS;
-       unsigned long _rem = fd % __NFDBITS;
-       return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
-{
-       unsigned int *tmp = (unsigned int *)p->fds_bits;
-       int i;
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
 
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-                       case 8:
-                               tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
-                               tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
-                               return;
-               }
-       }
-       i = __FDSET_LONGS;
-       while (i) {
-               i--;
-               *tmp = 0;
-               tmp++;
-       }
-}
+#include <asm-generic/posix_types.h>
 
-#endif /* defined(__KERNEL__) */
-#endif /* __GNUC__ */
 #endif /* _XTENSA_POSIX_TYPES_H */
index e3636520d8cc2d534735cd42b35d513c420fc79f..9fa8ad9793611f9d1c2295849b90f0444a2a9835 100644 (file)
@@ -13,4 +13,6 @@
 
 #define COMMAND_LINE_SIZE      256
 
+extern void set_except_vector(int n, void *addr);
+
 #endif
diff --git a/arch/xtensa/include/asm/switch_to.h b/arch/xtensa/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..6b73bf0
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SWITCH_TO_H
+#define _XTENSA_SWITCH_TO_H
+
+/* * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern void *_switch_to(void *last, void *next);
+
+#define switch_to(prev,next,last)              \
+do {                                           \
+       (last) = _switch_to(prev, next);        \
+} while(0)
+
+#endif /* _XTENSA_SWITCH_TO_H */
diff --git a/arch/xtensa/include/asm/system.h b/arch/xtensa/include/asm/system.h
deleted file mode 100644 (file)
index 1e7e09a..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * include/asm-xtensa/system.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SYSTEM_H
-#define _XTENSA_SYSTEM_H
-
-#include <linux/stringify.h>
-#include <linux/irqflags.h>
-
-#include <asm/processor.h>
-
-#define smp_read_barrier_depends() do { } while(0)
-#define read_barrier_depends() do { } while(0)
-
-#define mb()  barrier()
-#define rmb() mb()
-#define wmb() mb()
-
-#ifdef CONFIG_SMP
-#error smp_* not defined
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#endif
-
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-
-#if !defined (__ASSEMBLY__)
-
-/* * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- */
-extern void *_switch_to(void *last, void *next);
-
-#endif /* __ASSEMBLY__ */
-
-#define switch_to(prev,next,last)              \
-do {                                           \
-       (last) = _switch_to(prev, next);        \
-} while(0)
-
-/*
- * cmpxchg
- */
-
-static inline unsigned long
-__cmpxchg_u32(volatile int *p, int old, int new)
-{
-  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-                      "l32i    %0, %1, 0              \n\t"
-                      "bne     %0, %2, 1f             \n\t"
-                      "s32i    %3, %1, 0              \n\t"
-                      "1:                             \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
-                      "rsync                          \n\t"
-                      : "=&a" (old)
-                      : "a" (p), "a" (old), "r" (new)
-                      : "a15", "memory");
-  return old;
-}
-/* This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg(). */
-
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-       case 4:  return __cmpxchg_u32(ptr, old, new);
-       default: __cmpxchg_called_with_bad_pointer();
-                return old;
-       }
-}
-
-#define cmpxchg(ptr,o,n)                                                     \
-       ({ __typeof__(*(ptr)) _o_ = (o);                                      \
-          __typeof__(*(ptr)) _n_ = (n);                                      \
-          (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                       (unsigned long)_n_, sizeof (*(ptr))); \
-       })
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-/*
- * xchg_u32
- *
- * Note that a15 is used here because the register allocation
- * done by the compiler is not guaranteed and a window overflow
- * may not occur between the rsil and wsr instructions. By using
- * a15 in the rsil, the machine is guaranteed to be in a state
- * where no register reference will cause an overflow.
- */
-
-static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
-{
-  unsigned long tmp;
-  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-                      "l32i    %0, %1, 0              \n\t"
-                      "s32i    %2, %1, 0              \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
-                      "rsync                          \n\t"
-                      : "=&a" (tmp)
-                      : "a" (m), "a" (val)
-                      : "a15", "memory");
-  return tmp;
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-/*
- * This only works if the compiler isn't horribly bad at optimizing.
- * gcc-2.5.8 reportedly can't handle this, but I define that one to
- * be dead anyway.
- */
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static __inline__ unsigned long
-__xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-               case 4:
-                       return xchg_u32(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-extern void set_except_vector(int n, void *addr);
-
-static inline void spill_registers(void)
-{
-       unsigned int a0, ps;
-
-       __asm__ __volatile__ (
-               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
-               "mov    a12, a0\n\t"
-               "rsr    a13," __stringify(SAR) "\n\t"
-               "xsr    a14," __stringify(PS) "\n\t"
-               "movi   a0, _spill_registers\n\t"
-               "rsync\n\t"
-               "callx0 a0\n\t"
-               "mov    a0, a12\n\t"
-               "wsr    a13," __stringify(SAR) "\n\t"
-               "wsr    a14," __stringify(PS) "\n\t"
-               :: "a" (&a0), "a" (&ps)
-               : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
-}
-
-#define arch_align_stack(x) (x)
-
-#endif /* _XTENSA_SYSTEM_H */
index 3fa526fd3c9989a3b279e4720cbb03742739cb16..6e4bb3b791ab709c221840a5d6987f7067b268d1 100644 (file)
@@ -17,7 +17,9 @@
 #define _XTENSA_UACCESS_H
 
 #include <linux/errno.h>
+#ifndef __ASSEMBLY__
 #include <linux/prefetch.h>
+#endif
 #include <asm/types.h>
 
 #define VERIFY_READ    0
index 2c9004770c4e1d0ca3aa63a10128510bbccab659..6a2d6edf8f728af36bf4da4fc1587e79057bdf46 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/platform.h>
index 2dff698ab02e5ce1642248afa0f582b8aa0f112f..33eea4c16f121bde393508ed132bab7bd4d16d47 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/elf.h>
index 1e5a034fe01194b200796ea5e2da9d8885eee4fb..17e746f7be604023856417a8d05dab6fcf3a4b37 100644 (file)
@@ -34,7 +34,6 @@
 # include <linux/seq_file.h>
 #endif
 
-#include <asm/system.h>
 #include <asm/bootparam.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
index e64efac3b9db43e7383127ec56ee31030ec36ff3..bc1e14cf93692b811c09c7440c83d9309cc00834 100644 (file)
@@ -381,6 +381,25 @@ static __always_inline unsigned long *stack_pointer(struct task_struct *task)
        return sp;
 }
 
+static inline void spill_registers(void)
+{
+       unsigned int a0, ps;
+
+       __asm__ __volatile__ (
+               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
+               "mov    a12, a0\n\t"
+               "rsr    a13," __stringify(SAR) "\n\t"
+               "xsr    a14," __stringify(PS) "\n\t"
+               "movi   a0, _spill_registers\n\t"
+               "rsync\n\t"
+               "callx0 a0\n\t"
+               "mov    a0, a12\n\t"
+               "wsr    a13," __stringify(SAR) "\n\t"
+               "wsr    a14," __stringify(PS) "\n\t"
+               :: "a" (&a0), "a" (&ps)
+               : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
+}
+
 void show_trace(struct task_struct *task, unsigned long *sp)
 {
        unsigned long a0, a1, pc;
index e367e30264366d82c17dc66d157a2aa2534388bc..b17885a0b508fe82e84b012b89539caf3862dfed 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/cacheflush.h>
 #include <asm/hardirq.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 
 unsigned long asid_cache = ASID_USER_FIRST;
index 239461d8ea888c150877a18d017a190ff6f61631..e2700b21395b16f2548da0fb809f0066a61d0bd7 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 
 
index b19a18dd994fd0565897d2e0dfebfedaab230c36..e37615f310d731a2f3837304b3d7f18a039bb5e4 100644 (file)
@@ -445,6 +445,16 @@ int ec_transaction(u8 command,
 
 EXPORT_SYMBOL(ec_transaction);
 
+/* Get the handle to the EC device */
+acpi_handle ec_get_handle(void)
+{
+       if (!first_ec)
+               return NULL;
+       return first_ec->handle;
+}
+
+EXPORT_SYMBOL(ec_get_handle);
+
 void acpi_ec_block_transactions(void)
 {
        struct acpi_ec *ec = first_ec;
index 2801b418d7bb5a1abb88a854a0c5cec4221408de..d4d9cb7e016a0b2d5ea5663f039ae905f77ce92c 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/cpu.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
index f3f0fe7e255a23ef679f718324cbf9e2f16e3f31..45d8097ef4cf0d0aae43e8e0a3576613ca90fdd8 100644 (file)
@@ -23,7 +23,7 @@
  * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
  * are available, video.ko should be used to handle the device.
  *
- * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi,
+ * Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop,
  * sony_acpi,... can take care about backlight brightness.
  *
  * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
index 6ff612d099c350a1d706e1d81e84e02ac415039a..2059ee460b0c61cf48614283db428ff5675f5904 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/atm_eni.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/uaccess.h>
index 5072f8ac16fdc13d072d4fea67843388f07c41d2..86fed1b916957623130923714ce877c69543af37 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index b81210330aca90227945f14dd853d281085952f4..75fd691cd43ee1307d6e2c28f4b7687a702e6569 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/uaccess.h>
index 487a54739854780c71ebce5de87d405f4b656e5d..45d506363aba8f90c117bfa5c31d4ca046eb4630 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/atm_idt77105.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 
index 9e373ba203082f8bc0cb5757a011a3efccf7b291..d4386019af5d59657812021e608a506adde44fe3 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
-#include <asm/system.h>  
 #include <asm/io.h>  
 #include <linux/atomic.h>
 #include <asm/uaccess.h>  
index 90f1ccca9e5215824ab531da5b8eaa1d662015c2..02159345566c3d018d01d50f8309fc4bd680a1d1 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/capability.h>
 #include <linux/atm_suni.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <linux/atomic.h>
index d889f56e8d8cf64cae17fc3bdb4c8ce120afc246..abe4e20b07660bcec8fd9b1cac15878ae78c5f0e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index e38ad243b4bbec7104e305cada1d15199299e4f2..07cbbc6fddb4ceff6b8141ba57935047a40bab28 100644 (file)
@@ -71,7 +71,7 @@ static inline int is_dma_buf_file(struct file *file)
  * ops, or error in allocating struct dma_buf, will return negative error.
  *
  */
-struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
+struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
                                size_t size, int flags)
 {
        struct dma_buf *dmabuf;
@@ -80,7 +80,9 @@ struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
        if (WARN_ON(!priv || !ops
                          || !ops->map_dma_buf
                          || !ops->unmap_dma_buf
-                         || !ops->release)) {
+                         || !ops->release
+                         || !ops->kmap_atomic
+                         || !ops->kmap)) {
                return ERR_PTR(-EINVAL);
        }
 
@@ -107,17 +109,18 @@ EXPORT_SYMBOL_GPL(dma_buf_export);
 /**
  * dma_buf_fd - returns a file descriptor for the given dma_buf
  * @dmabuf:    [in]    pointer to dma_buf for which fd is required.
+ * @flags:      [in]    flags to give to fd
  *
  * On success, returns an associated 'fd'. Else, returns error.
  */
-int dma_buf_fd(struct dma_buf *dmabuf)
+int dma_buf_fd(struct dma_buf *dmabuf, int flags)
 {
        int error, fd;
 
        if (!dmabuf || !dmabuf->file)
                return -EINVAL;
 
-       error = get_unused_fd();
+       error = get_unused_fd_flags(flags);
        if (error < 0)
                return error;
        fd = error;
@@ -185,17 +188,18 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
        struct dma_buf_attachment *attach;
        int ret;
 
-       if (WARN_ON(!dmabuf || !dev || !dmabuf->ops))
+       if (WARN_ON(!dmabuf || !dev))
                return ERR_PTR(-EINVAL);
 
        attach = kzalloc(sizeof(struct dma_buf_attachment), GFP_KERNEL);
        if (attach == NULL)
-               goto err_alloc;
-
-       mutex_lock(&dmabuf->lock);
+               return ERR_PTR(-ENOMEM);
 
        attach->dev = dev;
        attach->dmabuf = dmabuf;
+
+       mutex_lock(&dmabuf->lock);
+
        if (dmabuf->ops->attach) {
                ret = dmabuf->ops->attach(dmabuf, dev, attach);
                if (ret)
@@ -206,8 +210,6 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
        mutex_unlock(&dmabuf->lock);
        return attach;
 
-err_alloc:
-       return ERR_PTR(-ENOMEM);
 err_attach:
        kfree(attach);
        mutex_unlock(&dmabuf->lock);
@@ -224,7 +226,7 @@ EXPORT_SYMBOL_GPL(dma_buf_attach);
  */
 void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
 {
-       if (WARN_ON(!dmabuf || !attach || !dmabuf->ops))
+       if (WARN_ON(!dmabuf || !attach))
                return;
 
        mutex_lock(&dmabuf->lock);
@@ -255,13 +257,10 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 
        might_sleep();
 
-       if (WARN_ON(!attach || !attach->dmabuf || !attach->dmabuf->ops))
+       if (WARN_ON(!attach || !attach->dmabuf))
                return ERR_PTR(-EINVAL);
 
-       mutex_lock(&attach->dmabuf->lock);
-       if (attach->dmabuf->ops->map_dma_buf)
-               sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
-       mutex_unlock(&attach->dmabuf->lock);
+       sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
 
        return sg_table;
 }
@@ -273,19 +272,137 @@ EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
  * dma_buf_ops.
  * @attach:    [in]    attachment to unmap buffer from
  * @sg_table:  [in]    scatterlist info of the buffer to unmap
+ * @direction:  [in]    direction of DMA transfer
  *
  */
 void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
-                               struct sg_table *sg_table)
+                               struct sg_table *sg_table,
+                               enum dma_data_direction direction)
 {
-       if (WARN_ON(!attach || !attach->dmabuf || !sg_table
-                           || !attach->dmabuf->ops))
+       if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
                return;
 
-       mutex_lock(&attach->dmabuf->lock);
-       if (attach->dmabuf->ops->unmap_dma_buf)
-               attach->dmabuf->ops->unmap_dma_buf(attach, sg_table);
-       mutex_unlock(&attach->dmabuf->lock);
-
+       attach->dmabuf->ops->unmap_dma_buf(attach, sg_table,
+                                               direction);
 }
 EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
+
+
+/**
+ * dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the
+ * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific
+ * preparations. Coherency is only guaranteed in the specified range for the
+ * specified access direction.
+ * @dma_buf:   [in]    buffer to prepare cpu access for.
+ * @start:     [in]    start of range for cpu access.
+ * @len:       [in]    length of range for cpu access.
+ * @direction: [in]    length of range for cpu access.
+ *
+ * Can return negative error values, returns 0 on success.
+ */
+int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+                            enum dma_data_direction direction)
+{
+       int ret = 0;
+
+       if (WARN_ON(!dmabuf))
+               return -EINVAL;
+
+       if (dmabuf->ops->begin_cpu_access)
+               ret = dmabuf->ops->begin_cpu_access(dmabuf, start, len, direction);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
+
+/**
+ * dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the
+ * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific
+ * actions. Coherency is only guaranteed in the specified range for the
+ * specified access direction.
+ * @dma_buf:   [in]    buffer to complete cpu access for.
+ * @start:     [in]    start of range for cpu access.
+ * @len:       [in]    length of range for cpu access.
+ * @direction: [in]    length of range for cpu access.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+                           enum dma_data_direction direction)
+{
+       WARN_ON(!dmabuf);
+
+       if (dmabuf->ops->end_cpu_access)
+               dmabuf->ops->end_cpu_access(dmabuf, start, len, direction);
+}
+EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
+
+/**
+ * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address
+ * space. The same restrictions as for kmap_atomic and friends apply.
+ * @dma_buf:   [in]    buffer to map page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to map.
+ *
+ * This call must always succeed, any necessary preparations that might fail
+ * need to be done in begin_cpu_access.
+ */
+void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
+{
+       WARN_ON(!dmabuf);
+
+       return dmabuf->ops->kmap_atomic(dmabuf, page_num);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
+
+/**
+ * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic.
+ * @dma_buf:   [in]    buffer to unmap page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to unmap.
+ * @vaddr:     [in]    kernel space pointer obtained from dma_buf_kmap_atomic.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned long page_num,
+                          void *vaddr)
+{
+       WARN_ON(!dmabuf);
+
+       if (dmabuf->ops->kunmap_atomic)
+               dmabuf->ops->kunmap_atomic(dmabuf, page_num, vaddr);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
+
+/**
+ * dma_buf_kmap - Map a page of the buffer object into kernel address space. The
+ * same restrictions as for kmap and friends apply.
+ * @dma_buf:   [in]    buffer to map page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to map.
+ *
+ * This call must always succeed, any necessary preparations that might fail
+ * need to be done in begin_cpu_access.
+ */
+void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
+{
+       WARN_ON(!dmabuf);
+
+       return dmabuf->ops->kmap(dmabuf, page_num);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kmap);
+
+/**
+ * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap.
+ * @dma_buf:   [in]    buffer to unmap page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to unmap.
+ * @vaddr:     [in]    kernel space pointer obtained from dma_buf_kmap.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num,
+                   void *vaddr)
+{
+       WARN_ON(!dmabuf);
+
+       if (dmabuf->ops->kunmap)
+               dmabuf->ops->kunmap(dmabuf, page_num, vaddr);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kunmap);
index 744f078f4dd8311caed330939afbcdc29c2da913..76a08236430a0f1d2e6ca02ad347433115d7145e 100644 (file)
@@ -202,7 +202,6 @@ static int slow_floppy;
 
 #include <asm/dma.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 static int FLOPPY_IRQ = 6;
 static int FLOPPY_DMA = 2;
index b52c9ca146fcbb6348e4d7a30a37ac9c1591bf2c..bf397bf108b75de4ef302dc7b8f66f45303b891f 100644 (file)
@@ -44,7 +44,6 @@
 #define HD_IRQ 14
 
 #define REALLY_SLOW_IO
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index c3f0ee16594dac8d33b92d2dafd02a6ee4e1526d..061427a75d375a5ed0655bdac8422e668a252a5e 100644 (file)
 #include <linux/kthread.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/types.h>
 
 #include <linux/nbd.h>
 
-#define LO_MAGIC 0x68797548
+#define NBD_MAGIC 0x68797548
 
 #ifdef NDEBUG
 #define dprintk(flags, fmt...)
@@ -116,7 +115,7 @@ static void nbd_end_request(struct request *req)
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
-static void sock_shutdown(struct nbd_device *lo, int lock)
+static void sock_shutdown(struct nbd_device *nbd, int lock)
 {
        /* Forcibly shutdown the socket causing all listeners
         * to error
@@ -125,14 +124,14 @@ static void sock_shutdown(struct nbd_device *lo, int lock)
         * there should be a more generic interface rather than
         * calling socket ops directly here */
        if (lock)
-               mutex_lock(&lo->tx_lock);
-       if (lo->sock) {
-               dev_warn(disk_to_dev(lo->disk), "shutting down socket\n");
-               kernel_sock_shutdown(lo->sock, SHUT_RDWR);
-               lo->sock = NULL;
+               mutex_lock(&nbd->tx_lock);
+       if (nbd->sock) {
+               dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
+               kernel_sock_shutdown(nbd->sock, SHUT_RDWR);
+               nbd->sock = NULL;
        }
        if (lock)
-               mutex_unlock(&lo->tx_lock);
+               mutex_unlock(&nbd->tx_lock);
 }
 
 static void nbd_xmit_timeout(unsigned long arg)
@@ -147,17 +146,17 @@ static void nbd_xmit_timeout(unsigned long arg)
 /*
  *  Send or receive packet.
  */
-static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
+static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
                int msg_flags)
 {
-       struct socket *sock = lo->sock;
+       struct socket *sock = nbd->sock;
        int result;
        struct msghdr msg;
        struct kvec iov;
        sigset_t blocked, oldset;
 
        if (unlikely(!sock)) {
-               dev_err(disk_to_dev(lo->disk),
+               dev_err(disk_to_dev(nbd->disk),
                        "Attempted %s on closed socket in sock_xmit\n",
                        (send ? "send" : "recv"));
                return -EINVAL;
@@ -181,15 +180,15 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
                if (send) {
                        struct timer_list ti;
 
-                       if (lo->xmit_timeout) {
+                       if (nbd->xmit_timeout) {
                                init_timer(&ti);
                                ti.function = nbd_xmit_timeout;
                                ti.data = (unsigned long)current;
-                               ti.expires = jiffies + lo->xmit_timeout;
+                               ti.expires = jiffies + nbd->xmit_timeout;
                                add_timer(&ti);
                        }
                        result = kernel_sendmsg(sock, &msg, &iov, 1, size);
-                       if (lo->xmit_timeout)
+                       if (nbd->xmit_timeout)
                                del_timer_sync(&ti);
                } else
                        result = kernel_recvmsg(sock, &msg, &iov, 1, size,
@@ -201,7 +200,7 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
                                task_pid_nr(current), current->comm,
                                dequeue_signal_lock(current, &current->blocked, &info));
                        result = -EINTR;
-                       sock_shutdown(lo, !send);
+                       sock_shutdown(nbd, !send);
                        break;
                }
 
@@ -219,18 +218,19 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
        return result;
 }
 
-static inline int sock_send_bvec(struct nbd_device *lo, struct bio_vec *bvec,
+static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec,
                int flags)
 {
        int result;
        void *kaddr = kmap(bvec->bv_page);
-       result = sock_xmit(lo, 1, kaddr + bvec->bv_offset, bvec->bv_len, flags);
+       result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset,
+                          bvec->bv_len, flags);
        kunmap(bvec->bv_page);
        return result;
 }
 
 /* always call with the tx_lock held */
-static int nbd_send_req(struct nbd_device *lo, struct request *req)
+static int nbd_send_req(struct nbd_device *nbd, struct request *req)
 {
        int result, flags;
        struct nbd_request request;
@@ -243,14 +243,14 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
        memcpy(request.handle, &req, sizeof(req));
 
        dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n",
-                       lo->disk->disk_name, req,
+                       nbd->disk->disk_name, req,
                        nbdcmd_to_ascii(nbd_cmd(req)),
                        (unsigned long long)blk_rq_pos(req) << 9,
                        blk_rq_bytes(req));
-       result = sock_xmit(lo, 1, &request, sizeof(request),
+       result = sock_xmit(nbd, 1, &request, sizeof(request),
                        (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
        if (result <= 0) {
-               dev_err(disk_to_dev(lo->disk),
+               dev_err(disk_to_dev(nbd->disk),
                        "Send control failed (result %d)\n", result);
                goto error_out;
        }
@@ -267,10 +267,10 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
                        if (!rq_iter_last(req, iter))
                                flags = MSG_MORE;
                        dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
-                                       lo->disk->disk_name, req, bvec->bv_len);
-                       result = sock_send_bvec(lo, bvec, flags);
+                                       nbd->disk->disk_name, req, bvec->bv_len);
+                       result = sock_send_bvec(nbd, bvec, flags);
                        if (result <= 0) {
-                               dev_err(disk_to_dev(lo->disk),
+                               dev_err(disk_to_dev(nbd->disk),
                                        "Send data failed (result %d)\n",
                                        result);
                                goto error_out;
@@ -283,25 +283,25 @@ error_out:
        return -EIO;
 }
 
-static struct request *nbd_find_request(struct nbd_device *lo,
+static struct request *nbd_find_request(struct nbd_device *nbd,
                                        struct request *xreq)
 {
        struct request *req, *tmp;
        int err;
 
-       err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
+       err = wait_event_interruptible(nbd->active_wq, nbd->active_req != xreq);
        if (unlikely(err))
                goto out;
 
-       spin_lock(&lo->queue_lock);
-       list_for_each_entry_safe(req, tmp, &lo->queue_head, queuelist) {
+       spin_lock(&nbd->queue_lock);
+       list_for_each_entry_safe(req, tmp, &nbd->queue_head, queuelist) {
                if (req != xreq)
                        continue;
                list_del_init(&req->queuelist);
-               spin_unlock(&lo->queue_lock);
+               spin_unlock(&nbd->queue_lock);
                return req;
        }
-       spin_unlock(&lo->queue_lock);
+       spin_unlock(&nbd->queue_lock);
 
        err = -ENOENT;
 
@@ -309,78 +309,78 @@ out:
        return ERR_PTR(err);
 }
 
-static inline int sock_recv_bvec(struct nbd_device *lo, struct bio_vec *bvec)
+static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
 {
        int result;
        void *kaddr = kmap(bvec->bv_page);
-       result = sock_xmit(lo, 0, kaddr + bvec->bv_offset, bvec->bv_len,
+       result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
                        MSG_WAITALL);
        kunmap(bvec->bv_page);
        return result;
 }
 
 /* NULL returned = something went wrong, inform userspace */
-static struct request *nbd_read_stat(struct nbd_device *lo)
+static struct request *nbd_read_stat(struct nbd_device *nbd)
 {
        int result;
        struct nbd_reply reply;
        struct request *req;
 
        reply.magic = 0;
-       result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
+       result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
        if (result <= 0) {
-               dev_err(disk_to_dev(lo->disk),
+               dev_err(disk_to_dev(nbd->disk),
                        "Receive control failed (result %d)\n", result);
                goto harderror;
        }
 
        if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
-               dev_err(disk_to_dev(lo->disk), "Wrong magic (0x%lx)\n",
+               dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)\n",
                                (unsigned long)ntohl(reply.magic));
                result = -EPROTO;
                goto harderror;
        }
 
-       req = nbd_find_request(lo, *(struct request **)reply.handle);
+       req = nbd_find_request(nbd, *(struct request **)reply.handle);
        if (IS_ERR(req)) {
                result = PTR_ERR(req);
                if (result != -ENOENT)
                        goto harderror;
 
-               dev_err(disk_to_dev(lo->disk), "Unexpected reply (%p)\n",
+               dev_err(disk_to_dev(nbd->disk), "Unexpected reply (%p)\n",
                        reply.handle);
                result = -EBADR;
                goto harderror;
        }
 
        if (ntohl(reply.error)) {
-               dev_err(disk_to_dev(lo->disk), "Other side returned error (%d)\n",
+               dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
                        ntohl(reply.error));
                req->errors++;
                return req;
        }
 
        dprintk(DBG_RX, "%s: request %p: got reply\n",
-                       lo->disk->disk_name, req);
+                       nbd->disk->disk_name, req);
        if (nbd_cmd(req) == NBD_CMD_READ) {
                struct req_iterator iter;
                struct bio_vec *bvec;
 
                rq_for_each_segment(bvec, req, iter) {
-                       result = sock_recv_bvec(lo, bvec);
+                       result = sock_recv_bvec(nbd, bvec);
                        if (result <= 0) {
-                               dev_err(disk_to_dev(lo->disk), "Receive data failed (result %d)\n",
+                               dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
                                        result);
                                req->errors++;
                                return req;
                        }
                        dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
-                               lo->disk->disk_name, req, bvec->bv_len);
+                               nbd->disk->disk_name, req, bvec->bv_len);
                }
        }
        return req;
 harderror:
-       lo->harderror = result;
+       nbd->harderror = result;
        return NULL;
 }
 
@@ -398,48 +398,48 @@ static struct device_attribute pid_attr = {
        .show = pid_show,
 };
 
-static int nbd_do_it(struct nbd_device *lo)
+static int nbd_do_it(struct nbd_device *nbd)
 {
        struct request *req;
        int ret;
 
-       BUG_ON(lo->magic != LO_MAGIC);
+       BUG_ON(nbd->magic != NBD_MAGIC);
 
-       lo->pid = task_pid_nr(current);
-       ret = device_create_file(disk_to_dev(lo->disk), &pid_attr);
+       nbd->pid = task_pid_nr(current);
+       ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
        if (ret) {
-               dev_err(disk_to_dev(lo->disk), "device_create_file failed!\n");
-               lo->pid = 0;
+               dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+               nbd->pid = 0;
                return ret;
        }
 
-       while ((req = nbd_read_stat(lo)) != NULL)
+       while ((req = nbd_read_stat(nbd)) != NULL)
                nbd_end_request(req);
 
-       device_remove_file(disk_to_dev(lo->disk), &pid_attr);
-       lo->pid = 0;
+       device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
+       nbd->pid = 0;
        return 0;
 }
 
-static void nbd_clear_que(struct nbd_device *lo)
+static void nbd_clear_que(struct nbd_device *nbd)
 {
        struct request *req;
 
-       BUG_ON(lo->magic != LO_MAGIC);
+       BUG_ON(nbd->magic != NBD_MAGIC);
 
        /*
-        * Because we have set lo->sock to NULL under the tx_lock, all
+        * Because we have set nbd->sock to NULL under the tx_lock, all
         * modifications to the list must have completed by now.  For
         * the same reason, the active_req must be NULL.
         *
         * As a consequence, we don't need to take the spin lock while
         * purging the list here.
         */
-       BUG_ON(lo->sock);
-       BUG_ON(lo->active_req);
+       BUG_ON(nbd->sock);
+       BUG_ON(nbd->active_req);
 
-       while (!list_empty(&lo->queue_head)) {
-               req = list_entry(lo->queue_head.next, struct request,
+       while (!list_empty(&nbd->queue_head)) {
+               req = list_entry(nbd->queue_head.next, struct request,
                                 queuelist);
                list_del_init(&req->queuelist);
                req->errors++;
@@ -448,7 +448,7 @@ static void nbd_clear_que(struct nbd_device *lo)
 }
 
 
-static void nbd_handle_req(struct nbd_device *lo, struct request *req)
+static void nbd_handle_req(struct nbd_device *nbd, struct request *req)
 {
        if (req->cmd_type != REQ_TYPE_FS)
                goto error_out;
@@ -456,8 +456,8 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
        nbd_cmd(req) = NBD_CMD_READ;
        if (rq_data_dir(req) == WRITE) {
                nbd_cmd(req) = NBD_CMD_WRITE;
-               if (lo->flags & NBD_READ_ONLY) {
-                       dev_err(disk_to_dev(lo->disk),
+               if (nbd->flags & NBD_READ_ONLY) {
+                       dev_err(disk_to_dev(nbd->disk),
                                "Write on read-only\n");
                        goto error_out;
                }
@@ -465,29 +465,29 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
 
        req->errors = 0;
 
-       mutex_lock(&lo->tx_lock);
-       if (unlikely(!lo->sock)) {
-               mutex_unlock(&lo->tx_lock);
-               dev_err(disk_to_dev(lo->disk),
+       mutex_lock(&nbd->tx_lock);
+       if (unlikely(!nbd->sock)) {
+               mutex_unlock(&nbd->tx_lock);
+               dev_err(disk_to_dev(nbd->disk),
                        "Attempted send on closed socket\n");
                goto error_out;
        }
 
-       lo->active_req = req;
+       nbd->active_req = req;
 
-       if (nbd_send_req(lo, req) != 0) {
-               dev_err(disk_to_dev(lo->disk), "Request send failed\n");
+       if (nbd_send_req(nbd, req) != 0) {
+               dev_err(disk_to_dev(nbd->disk), "Request send failed\n");
                req->errors++;
                nbd_end_request(req);
        } else {
-               spin_lock(&lo->queue_lock);
-               list_add(&req->queuelist, &lo->queue_head);
-               spin_unlock(&lo->queue_lock);
+               spin_lock(&nbd->queue_lock);
+               list_add(&req->queuelist, &nbd->queue_head);
+               spin_unlock(&nbd->queue_lock);
        }
 
-       lo->active_req = NULL;
-       mutex_unlock(&lo->tx_lock);
-       wake_up_all(&lo->active_wq);
+       nbd->active_req = NULL;
+       mutex_unlock(&nbd->tx_lock);
+       wake_up_all(&nbd->active_wq);
 
        return;
 
@@ -498,28 +498,28 @@ error_out:
 
 static int nbd_thread(void *data)
 {
-       struct nbd_device *lo = data;
+       struct nbd_device *nbd = data;
        struct request *req;
 
        set_user_nice(current, -20);
-       while (!kthread_should_stop() || !list_empty(&lo->waiting_queue)) {
+       while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
                /* wait for something to do */
-               wait_event_interruptible(lo->waiting_wq,
+               wait_event_interruptible(nbd->waiting_wq,
                                         kthread_should_stop() ||
-                                        !list_empty(&lo->waiting_queue));
+                                        !list_empty(&nbd->waiting_queue));
 
                /* extract request */
-               if (list_empty(&lo->waiting_queue))
+               if (list_empty(&nbd->waiting_queue))
                        continue;
 
-               spin_lock_irq(&lo->queue_lock);
-               req = list_entry(lo->waiting_queue.next, struct request,
+               spin_lock_irq(&nbd->queue_lock);
+               req = list_entry(nbd->waiting_queue.next, struct request,
                                 queuelist);
                list_del_init(&req->queuelist);
-               spin_unlock_irq(&lo->queue_lock);
+               spin_unlock_irq(&nbd->queue_lock);
 
                /* handle request */
-               nbd_handle_req(lo, req);
+               nbd_handle_req(nbd, req);
        }
        return 0;
 }
@@ -527,7 +527,7 @@ static int nbd_thread(void *data)
 /*
  * We always wait for result of write, for now. It would be nice to make it optional
  * in future
- * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
+ * if ((rq_data_dir(req) == WRITE) && (nbd->flags & NBD_WRITE_NOCHK))
  *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
  */
 
@@ -536,19 +536,19 @@ static void do_nbd_request(struct request_queue *q)
        struct request *req;
        
        while ((req = blk_fetch_request(q)) != NULL) {
-               struct nbd_device *lo;
+               struct nbd_device *nbd;
 
                spin_unlock_irq(q->queue_lock);
 
                dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
                                req->rq_disk->disk_name, req, req->cmd_type);
 
-               lo = req->rq_disk->private_data;
+               nbd = req->rq_disk->private_data;
 
-               BUG_ON(lo->magic != LO_MAGIC);
+               BUG_ON(nbd->magic != NBD_MAGIC);
 
-               if (unlikely(!lo->sock)) {
-                       dev_err(disk_to_dev(lo->disk),
+               if (unlikely(!nbd->sock)) {
+                       dev_err(disk_to_dev(nbd->disk),
                                "Attempted send on closed socket\n");
                        req->errors++;
                        nbd_end_request(req);
@@ -556,11 +556,11 @@ static void do_nbd_request(struct request_queue *q)
                        continue;
                }
 
-               spin_lock_irq(&lo->queue_lock);
-               list_add_tail(&req->queuelist, &lo->waiting_queue);
-               spin_unlock_irq(&lo->queue_lock);
+               spin_lock_irq(&nbd->queue_lock);
+               list_add_tail(&req->queuelist, &nbd->waiting_queue);
+               spin_unlock_irq(&nbd->queue_lock);
 
-               wake_up(&lo->waiting_wq);
+               wake_up(&nbd->waiting_wq);
 
                spin_lock_irq(q->queue_lock);
        }
@@ -568,32 +568,32 @@ static void do_nbd_request(struct request_queue *q)
 
 /* Must be called with tx_lock held */
 
-static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
+static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                       unsigned int cmd, unsigned long arg)
 {
        switch (cmd) {
        case NBD_DISCONNECT: {
                struct request sreq;
 
-               dev_info(disk_to_dev(lo->disk), "NBD_DISCONNECT\n");
+               dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
 
                blk_rq_init(NULL, &sreq);
                sreq.cmd_type = REQ_TYPE_SPECIAL;
                nbd_cmd(&sreq) = NBD_CMD_DISC;
-               if (!lo->sock)
+               if (!nbd->sock)
                        return -EINVAL;
-               nbd_send_req(lo, &sreq);
+               nbd_send_req(nbd, &sreq);
                 return 0;
        }
  
        case NBD_CLEAR_SOCK: {
                struct file *file;
 
-               lo->sock = NULL;
-               file = lo->file;
-               lo->file = NULL;
-               nbd_clear_que(lo);
-               BUG_ON(!list_empty(&lo->queue_head));
+               nbd->sock = NULL;
+               file = nbd->file;
+               nbd->file = NULL;
+               nbd_clear_que(nbd);
+               BUG_ON(!list_empty(&nbd->queue_head));
                if (file)
                        fput(file);
                return 0;
@@ -601,14 +601,14 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
 
        case NBD_SET_SOCK: {
                struct file *file;
-               if (lo->file)
+               if (nbd->file)
                        return -EBUSY;
                file = fget(arg);
                if (file) {
                        struct inode *inode = file->f_path.dentry->d_inode;
                        if (S_ISSOCK(inode->i_mode)) {
-                               lo->file = file;
-                               lo->sock = SOCKET_I(inode);
+                               nbd->file = file;
+                               nbd->sock = SOCKET_I(inode);
                                if (max_part > 0)
                                        bdev->bd_invalidated = 1;
                                return 0;
@@ -620,29 +620,29 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
        }
 
        case NBD_SET_BLKSIZE:
-               lo->blksize = arg;
-               lo->bytesize &= ~(lo->blksize-1);
-               bdev->bd_inode->i_size = lo->bytesize;
-               set_blocksize(bdev, lo->blksize);
-               set_capacity(lo->disk, lo->bytesize >> 9);
+               nbd->blksize = arg;
+               nbd->bytesize &= ~(nbd->blksize-1);
+               bdev->bd_inode->i_size = nbd->bytesize;
+               set_blocksize(bdev, nbd->blksize);
+               set_capacity(nbd->disk, nbd->bytesize >> 9);
                return 0;
 
        case NBD_SET_SIZE:
-               lo->bytesize = arg & ~(lo->blksize-1);
-               bdev->bd_inode->i_size = lo->bytesize;
-               set_blocksize(bdev, lo->blksize);
-               set_capacity(lo->disk, lo->bytesize >> 9);
+               nbd->bytesize = arg & ~(nbd->blksize-1);
+               bdev->bd_inode->i_size = nbd->bytesize;
+               set_blocksize(bdev, nbd->blksize);
+               set_capacity(nbd->disk, nbd->bytesize >> 9);
                return 0;
 
        case NBD_SET_TIMEOUT:
-               lo->xmit_timeout = arg * HZ;
+               nbd->xmit_timeout = arg * HZ;
                return 0;
 
        case NBD_SET_SIZE_BLOCKS:
-               lo->bytesize = ((u64) arg) * lo->blksize;
-               bdev->bd_inode->i_size = lo->bytesize;
-               set_blocksize(bdev, lo->blksize);
-               set_capacity(lo->disk, lo->bytesize >> 9);
+               nbd->bytesize = ((u64) arg) * nbd->blksize;
+               bdev->bd_inode->i_size = nbd->bytesize;
+               set_blocksize(bdev, nbd->blksize);
+               set_capacity(nbd->disk, nbd->bytesize >> 9);
                return 0;
 
        case NBD_DO_IT: {
@@ -650,38 +650,38 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
                struct file *file;
                int error;
 
-               if (lo->pid)
+               if (nbd->pid)
                        return -EBUSY;
-               if (!lo->file)
+               if (!nbd->file)
                        return -EINVAL;
 
-               mutex_unlock(&lo->tx_lock);
+               mutex_unlock(&nbd->tx_lock);
 
-               thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
+               thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name);
                if (IS_ERR(thread)) {
-                       mutex_lock(&lo->tx_lock);
+                       mutex_lock(&nbd->tx_lock);
                        return PTR_ERR(thread);
                }
                wake_up_process(thread);
-               error = nbd_do_it(lo);
+               error = nbd_do_it(nbd);
                kthread_stop(thread);
 
-               mutex_lock(&lo->tx_lock);
+               mutex_lock(&nbd->tx_lock);
                if (error)
                        return error;
-               sock_shutdown(lo, 0);
-               file = lo->file;
-               lo->file = NULL;
-               nbd_clear_que(lo);
-               dev_warn(disk_to_dev(lo->disk), "queue cleared\n");
+               sock_shutdown(nbd, 0);
+               file = nbd->file;
+               nbd->file = NULL;
+               nbd_clear_que(nbd);
+               dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
                if (file)
                        fput(file);
-               lo->bytesize = 0;
+               nbd->bytesize = 0;
                bdev->bd_inode->i_size = 0;
-               set_capacity(lo->disk, 0);
+               set_capacity(nbd->disk, 0);
                if (max_part > 0)
                        ioctl_by_bdev(bdev, BLKRRPART, 0);
-               return lo->harderror;
+               return nbd->harderror;
        }
 
        case NBD_CLEAR_QUE:
@@ -689,14 +689,14 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
                 * This is for compatibility only.  The queue is always cleared
                 * by NBD_DO_IT or NBD_CLEAR_SOCK.
                 */
-               BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
+               BUG_ON(!nbd->sock && !list_empty(&nbd->queue_head));
                return 0;
 
        case NBD_PRINT_DEBUG:
-               dev_info(disk_to_dev(lo->disk),
+               dev_info(disk_to_dev(nbd->disk),
                        "next = %p, prev = %p, head = %p\n",
-                       lo->queue_head.next, lo->queue_head.prev,
-                       &lo->queue_head);
+                       nbd->queue_head.next, nbd->queue_head.prev,
+                       &nbd->queue_head);
                return 0;
        }
        return -ENOTTY;
@@ -705,21 +705,21 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
 static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
                     unsigned int cmd, unsigned long arg)
 {
-       struct nbd_device *lo = bdev->bd_disk->private_data;
+       struct nbd_device *nbd = bdev->bd_disk->private_data;
        int error;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       BUG_ON(lo->magic != LO_MAGIC);
+       BUG_ON(nbd->magic != NBD_MAGIC);
 
        /* Anyone capable of this syscall can do *real bad* things */
        dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
-                       lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
+               nbd->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
 
-       mutex_lock(&lo->tx_lock);
-       error = __nbd_ioctl(bdev, lo, cmd, arg);
-       mutex_unlock(&lo->tx_lock);
+       mutex_lock(&nbd->tx_lock);
+       error = __nbd_ioctl(bdev, nbd, cmd, arg);
+       mutex_unlock(&nbd->tx_lock);
 
        return error;
 }
@@ -805,7 +805,7 @@ static int __init nbd_init(void)
        for (i = 0; i < nbds_max; i++) {
                struct gendisk *disk = nbd_dev[i].disk;
                nbd_dev[i].file = NULL;
-               nbd_dev[i].magic = LO_MAGIC;
+               nbd_dev[i].magic = NBD_MAGIC;
                nbd_dev[i].flags = 0;
                INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
                spin_lock_init(&nbd_dev[i].queue_lock);
index 48e8fee9f2d4f8aa6bacf4243694a430b53fdae9..9dcf76a10bb64584b2d43bfbcc4d06a735711f43 100644 (file)
@@ -839,10 +839,7 @@ static struct vio_driver vdc_port_driver = {
        .id_table       = vdc_port_match,
        .probe          = vdc_port_probe,
        .remove         = vdc_port_remove,
-       .driver         = {
-               .name   = "vdc_port",
-               .owner  = THIS_MODULE,
-       }
+       .name           = "vdc_port",
 };
 
 static int __init vdc_init(void)
index 51a972704db503932d39e9ab917480af232bf4ce..ff540520bada14766b9ca817bbeb2697a426e0a1 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/io.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
 
index 9c09d6f05dc94e0abfbe0247bb514b203a51f819..308c8599ab55ca480c364cab3b40bc6f41d94faf 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <linux/device.h>
index 194224d07f7c391cbdb86cc025d27f6386a88f3e..c4fc2f3fc32cad477afb98051100f4bc9d023b3f 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <pcmcia/cistpl.h>
index 049c0594a76b94b82f021409f7a4cdea2bc5cd4c..6e8d9618968443df06710d52666aaf5e5c2af3bd 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <pcmcia/cistpl.h>
index f4837a893dfad64dcd0f49b5a73fb61f76b948b6..57501ca9204b017abce7b6a8f160a8e74769544e 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kthread.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 
 /*
  * The apm_bios device is one of the misc char devices.
index ed8303f9890c346ef136d54ec2b999cce3ee5e5d..7d34b203718af7bd9fd5c3a00ca294e5c7a8dea8 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/rtc.h>
 #if defined(CONFIG_M32R)
 #include <asm/m32r.h>
index 53c524e7b82928a78ff04e26be135ca4c1a4e428..a082d00b0f115f0c0d9dfcca07ade43c9f15070e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/efi.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define EFI_RTC_VERSION                "0.4"
 
index f773a9dd14f38ea2e1b5b2d3adcfd11f472f9ea3..21cb980f115782a2e80c4f46c442585f75ca806d 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/rtc.h>
 
 /*
index 0833896cf6f2aeb98721441619a9fdeae0ae54bb..3845ab44c3304e1d2e4ce0f8bfc7455cd5ef6717 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/io.h>
 
 #include <asm/current.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
 
index 2aa3977aae5e35d28f897416d89e53731a5c38ee..9eb360ff8cab0cc19178b6412ade5f4cf3d40e18 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
index cf82fedae09975272fd6517b1fa5346eff95a814..e53fc24c6af3e1b97ea95052dd383efc26138eb3 100644 (file)
@@ -118,8 +118,8 @@ enum kcs_states {
 #define MAX_KCS_WRITE_SIZE IPMI_MAX_MSG_LENGTH
 
 /* Timeouts in microseconds. */
-#define IBF_RETRY_TIMEOUT 1000000
-#define OBF_RETRY_TIMEOUT 1000000
+#define IBF_RETRY_TIMEOUT 5000000
+#define OBF_RETRY_TIMEOUT 5000000
 #define MAX_ERROR_RETRIES 10
 #define ERROR0_OBF_WAIT_JIFFIES (2*HZ)
 
index 58c0e6387cf73ddfd016baeb38384e08f5a6f794..2c29942b132654747af55e6b70ea4857dc9e0de4 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
@@ -46,6 +45,7 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/rcupdate.h>
+#include <linux/interrupt.h>
 
 #define PFX "IPMI message handler: "
 
@@ -53,6 +53,8 @@
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
+static void smi_recv_tasklet(unsigned long);
+static void handle_new_recv_msgs(ipmi_smi_t intf);
 
 static int initialized;
 
@@ -355,12 +357,15 @@ struct ipmi_smi {
        int curr_seq;
 
        /*
-        * Messages that were delayed for some reason (out of memory,
-        * for instance), will go in here to be processed later in a
-        * periodic timer interrupt.
+        * Messages queued for delivery.  If delivery fails (out of memory
+        * for instance), They will stay in here to be processed later in a
+        * periodic timer interrupt.  The tasklet is for handling received
+        * messages directly from the handler.
         */
        spinlock_t       waiting_msgs_lock;
        struct list_head waiting_msgs;
+       atomic_t         watchdog_pretimeouts_to_deliver;
+       struct tasklet_struct recv_tasklet;
 
        /*
         * The list of command receivers that are registered for commands
@@ -493,6 +498,8 @@ static void clean_up_interface_data(ipmi_smi_t intf)
        struct cmd_rcvr  *rcvr, *rcvr2;
        struct list_head list;
 
+       tasklet_kill(&intf->recv_tasklet);
+
        free_smi_msg_list(&intf->waiting_msgs);
        free_recv_msg_list(&intf->waiting_events);
 
@@ -2786,12 +2793,17 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
        return;
 }
 
-void ipmi_poll_interface(ipmi_user_t user)
+static void ipmi_poll(ipmi_smi_t intf)
 {
-       ipmi_smi_t intf = user->intf;
-
        if (intf->handlers->poll)
                intf->handlers->poll(intf->send_info);
+       /* In case something came in */
+       handle_new_recv_msgs(intf);
+}
+
+void ipmi_poll_interface(ipmi_user_t user)
+{
+       ipmi_poll(user->intf);
 }
 EXPORT_SYMBOL(ipmi_poll_interface);
 
@@ -2860,6 +2872,10 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
 #endif
        spin_lock_init(&intf->waiting_msgs_lock);
        INIT_LIST_HEAD(&intf->waiting_msgs);
+       tasklet_init(&intf->recv_tasklet,
+                    smi_recv_tasklet,
+                    (unsigned long) intf);
+       atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0);
        spin_lock_init(&intf->events_lock);
        INIT_LIST_HEAD(&intf->waiting_events);
        intf->waiting_events_count = 0;
@@ -3622,11 +3638,11 @@ static int handle_bmc_rsp(ipmi_smi_t          intf,
 }
 
 /*
- * Handle a new message.  Return 1 if the message should be requeued,
+ * Handle a received message.  Return 1 if the message should be requeued,
  * 0 if the message should be freed, or -1 if the message should not
  * be freed or requeued.
  */
-static int handle_new_recv_msg(ipmi_smi_t          intf,
+static int handle_one_recv_msg(ipmi_smi_t          intf,
                               struct ipmi_smi_msg *msg)
 {
        int requeue;
@@ -3784,12 +3800,72 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
        return requeue;
 }
 
+/*
+ * If there are messages in the queue or pretimeouts, handle them.
+ */
+static void handle_new_recv_msgs(ipmi_smi_t intf)
+{
+       struct ipmi_smi_msg  *smi_msg;
+       unsigned long        flags = 0;
+       int                  rv;
+       int                  run_to_completion = intf->run_to_completion;
+
+       /* See if any waiting messages need to be processed. */
+       if (!run_to_completion)
+               spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+       while (!list_empty(&intf->waiting_msgs)) {
+               smi_msg = list_entry(intf->waiting_msgs.next,
+                                    struct ipmi_smi_msg, link);
+               list_del(&smi_msg->link);
+               if (!run_to_completion)
+                       spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+               rv = handle_one_recv_msg(intf, smi_msg);
+               if (!run_to_completion)
+                       spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+               if (rv == 0) {
+                       /* Message handled */
+                       ipmi_free_smi_msg(smi_msg);
+               } else if (rv < 0) {
+                       /* Fatal error on the message, del but don't free. */
+               } else {
+                       /*
+                        * To preserve message order, quit if we
+                        * can't handle a message.
+                        */
+                       list_add(&smi_msg->link, &intf->waiting_msgs);
+                       break;
+               }
+       }
+       if (!run_to_completion)
+               spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+
+       /*
+        * If the pretimout count is non-zero, decrement one from it and
+        * deliver pretimeouts to all the users.
+        */
+       if (atomic_add_unless(&intf->watchdog_pretimeouts_to_deliver, -1, 0)) {
+               ipmi_user_t user;
+
+               rcu_read_lock();
+               list_for_each_entry_rcu(user, &intf->users, link) {
+                       if (user->handler->ipmi_watchdog_pretimeout)
+                               user->handler->ipmi_watchdog_pretimeout(
+                                       user->handler_data);
+               }
+               rcu_read_unlock();
+       }
+}
+
+static void smi_recv_tasklet(unsigned long val)
+{
+       handle_new_recv_msgs((ipmi_smi_t) val);
+}
+
 /* Handle a new message from the lower layer. */
 void ipmi_smi_msg_received(ipmi_smi_t          intf,
                           struct ipmi_smi_msg *msg)
 {
        unsigned long flags = 0; /* keep us warning-free. */
-       int           rv;
        int           run_to_completion;
 
 
@@ -3843,31 +3919,11 @@ void ipmi_smi_msg_received(ipmi_smi_t          intf,
        run_to_completion = intf->run_to_completion;
        if (!run_to_completion)
                spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
-       if (!list_empty(&intf->waiting_msgs)) {
-               list_add_tail(&msg->link, &intf->waiting_msgs);
-               if (!run_to_completion)
-                       spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
-               goto out;
-       }
+       list_add_tail(&msg->link, &intf->waiting_msgs);
        if (!run_to_completion)
                spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
 
-       rv = handle_new_recv_msg(intf, msg);
-       if (rv > 0) {
-               /*
-                * Could not handle the message now, just add it to a
-                * list to handle later.
-                */
-               run_to_completion = intf->run_to_completion;
-               if (!run_to_completion)
-                       spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
-               list_add_tail(&msg->link, &intf->waiting_msgs);
-               if (!run_to_completion)
-                       spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
-       } else if (rv == 0) {
-               ipmi_free_smi_msg(msg);
-       }
-
+       tasklet_schedule(&intf->recv_tasklet);
  out:
        return;
 }
@@ -3875,16 +3931,8 @@ EXPORT_SYMBOL(ipmi_smi_msg_received);
 
 void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
 {
-       ipmi_user_t user;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(user, &intf->users, link) {
-               if (!user->handler->ipmi_watchdog_pretimeout)
-                       continue;
-
-               user->handler->ipmi_watchdog_pretimeout(user->handler_data);
-       }
-       rcu_read_unlock();
+       atomic_set(&intf->watchdog_pretimeouts_to_deliver, 1);
+       tasklet_schedule(&intf->recv_tasklet);
 }
 EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
 
@@ -3998,28 +4046,12 @@ static void ipmi_timeout_handler(long timeout_period)
        ipmi_smi_t           intf;
        struct list_head     timeouts;
        struct ipmi_recv_msg *msg, *msg2;
-       struct ipmi_smi_msg  *smi_msg, *smi_msg2;
        unsigned long        flags;
        int                  i;
 
        rcu_read_lock();
        list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
-               /* See if any waiting messages need to be processed. */
-               spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
-               list_for_each_entry_safe(smi_msg, smi_msg2,
-                                        &intf->waiting_msgs, link) {
-                       if (!handle_new_recv_msg(intf, smi_msg)) {
-                               list_del(&smi_msg->link);
-                               ipmi_free_smi_msg(smi_msg);
-                       } else {
-                               /*
-                                * To preserve message order, quit if we
-                                * can't handle a message.
-                                */
-                               break;
-                       }
-               }
-               spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+               tasklet_schedule(&intf->recv_tasklet);
 
                /*
                 * Go through the seq table and find any messages that
@@ -4173,12 +4205,48 @@ EXPORT_SYMBOL(ipmi_free_recv_msg);
 
 #ifdef CONFIG_IPMI_PANIC_EVENT
 
+static atomic_t panic_done_count = ATOMIC_INIT(0);
+
 static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
 {
+       atomic_dec(&panic_done_count);
 }
 
 static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
 {
+       atomic_dec(&panic_done_count);
+}
+
+/*
+ * Inside a panic, send a message and wait for a response.
+ */
+static void ipmi_panic_request_and_wait(ipmi_smi_t           intf,
+                                       struct ipmi_addr     *addr,
+                                       struct kernel_ipmi_msg *msg)
+{
+       struct ipmi_smi_msg  smi_msg;
+       struct ipmi_recv_msg recv_msg;
+       int rv;
+
+       smi_msg.done = dummy_smi_done_handler;
+       recv_msg.done = dummy_recv_done_handler;
+       atomic_add(2, &panic_done_count);
+       rv = i_ipmi_request(NULL,
+                           intf,
+                           addr,
+                           0,
+                           msg,
+                           intf,
+                           &smi_msg,
+                           &recv_msg,
+                           0,
+                           intf->channels[0].address,
+                           intf->channels[0].lun,
+                           0, 1); /* Don't retry, and don't wait. */
+       if (rv)
+               atomic_sub(2, &panic_done_count);
+       while (atomic_read(&panic_done_count) != 0)
+               ipmi_poll(intf);
 }
 
 #ifdef CONFIG_IPMI_PANIC_STRING
@@ -4217,8 +4285,6 @@ static void send_panic_events(char *str)
        unsigned char                     data[16];
        struct ipmi_system_interface_addr *si;
        struct ipmi_addr                  addr;
-       struct ipmi_smi_msg               smi_msg;
-       struct ipmi_recv_msg              recv_msg;
 
        si = (struct ipmi_system_interface_addr *) &addr;
        si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
@@ -4246,9 +4312,6 @@ static void send_panic_events(char *str)
                data[7] = str[2];
        }
 
-       smi_msg.done = dummy_smi_done_handler;
-       recv_msg.done = dummy_recv_done_handler;
-
        /* For every registered interface, send the event. */
        list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
                if (!intf->handlers)
@@ -4258,18 +4321,7 @@ static void send_panic_events(char *str)
                intf->run_to_completion = 1;
                /* Send the event announcing the panic. */
                intf->handlers->set_run_to_completion(intf->send_info, 1);
-               i_ipmi_request(NULL,
-                              intf,
-                              &addr,
-                              0,
-                              &msg,
-                              intf,
-                              &smi_msg,
-                              &recv_msg,
-                              0,
-                              intf->channels[0].address,
-                              intf->channels[0].lun,
-                              0, 1); /* Don't retry, and don't wait. */
+               ipmi_panic_request_and_wait(intf, &addr, &msg);
        }
 
 #ifdef CONFIG_IPMI_PANIC_STRING
@@ -4317,18 +4369,7 @@ static void send_panic_events(char *str)
                msg.data = NULL;
                msg.data_len = 0;
                intf->null_user_handler = device_id_fetcher;
-               i_ipmi_request(NULL,
-                              intf,
-                              &addr,
-                              0,
-                              &msg,
-                              intf,
-                              &smi_msg,
-                              &recv_msg,
-                              0,
-                              intf->channels[0].address,
-                              intf->channels[0].lun,
-                              0, 1); /* Don't retry, and don't wait. */
+               ipmi_panic_request_and_wait(intf, &addr, &msg);
 
                if (intf->local_event_generator) {
                        /* Request the event receiver from the local MC. */
@@ -4337,18 +4378,7 @@ static void send_panic_events(char *str)
                        msg.data = NULL;
                        msg.data_len = 0;
                        intf->null_user_handler = event_receiver_fetcher;
-                       i_ipmi_request(NULL,
-                                      intf,
-                                      &addr,
-                                      0,
-                                      &msg,
-                                      intf,
-                                      &smi_msg,
-                                      &recv_msg,
-                                      0,
-                                      intf->channels[0].address,
-                                      intf->channels[0].lun,
-                                      0, 1); /* no retry, and no wait. */
+                       ipmi_panic_request_and_wait(intf, &addr, &msg);
                }
                intf->null_user_handler = NULL;
 
@@ -4405,18 +4435,7 @@ static void send_panic_events(char *str)
                        strncpy(data+5, p, 11);
                        p += size;
 
-                       i_ipmi_request(NULL,
-                                      intf,
-                                      &addr,
-                                      0,
-                                      &msg,
-                                      intf,
-                                      &smi_msg,
-                                      &recv_msg,
-                                      0,
-                                      intf->channels[0].address,
-                                      intf->channels[0].lun,
-                                      0, 1); /* no retry, and no wait. */
+                       ipmi_panic_request_and_wait(intf, &addr, &msg);
                }
        }
 #endif /* CONFIG_IPMI_PANIC_STRING */
index 50fcf9c04569a18007816dc322382103a604c542..1e638fff40ea2cb01d99d33745ae5f6526787237 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <asm/system.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/timer.h>
@@ -171,7 +170,6 @@ struct smi_info {
        struct si_sm_handlers  *handlers;
        enum si_type           si_type;
        spinlock_t             si_lock;
-       spinlock_t             msg_lock;
        struct list_head       xmit_msgs;
        struct list_head       hp_xmit_msgs;
        struct ipmi_smi_msg    *curr_msg;
@@ -320,16 +318,8 @@ static int register_xaction_notifier(struct notifier_block *nb)
 static void deliver_recv_msg(struct smi_info *smi_info,
                             struct ipmi_smi_msg *msg)
 {
-       /* Deliver the message to the upper layer with the lock
-          released. */
-
-       if (smi_info->run_to_completion) {
-               ipmi_smi_msg_received(smi_info->intf, msg);
-       } else {
-               spin_unlock(&(smi_info->si_lock));
-               ipmi_smi_msg_received(smi_info->intf, msg);
-               spin_lock(&(smi_info->si_lock));
-       }
+       /* Deliver the message to the upper layer. */
+       ipmi_smi_msg_received(smi_info->intf, msg);
 }
 
 static void return_hosed_msg(struct smi_info *smi_info, int cCode)
@@ -358,13 +348,6 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
        struct timeval t;
 #endif
 
-       /*
-        * No need to save flags, we aleady have interrupts off and we
-        * already hold the SMI lock.
-        */
-       if (!smi_info->run_to_completion)
-               spin_lock(&(smi_info->msg_lock));
-
        /* Pick the high priority queue first. */
        if (!list_empty(&(smi_info->hp_xmit_msgs))) {
                entry = smi_info->hp_xmit_msgs.next;
@@ -402,9 +385,6 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
                rv = SI_SM_CALL_WITHOUT_DELAY;
        }
  out:
-       if (!smi_info->run_to_completion)
-               spin_unlock(&(smi_info->msg_lock));
-
        return rv;
 }
 
@@ -481,9 +461,7 @@ static void handle_flags(struct smi_info *smi_info)
 
                start_clear_flags(smi_info);
                smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
-               spin_unlock(&(smi_info->si_lock));
                ipmi_smi_watchdog_pretimeout(smi_info->intf);
-               spin_lock(&(smi_info->si_lock));
        } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
                /* Messages available. */
                smi_info->curr_msg = ipmi_alloc_smi_msg();
@@ -889,19 +867,6 @@ static void sender(void                *send_info,
        printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
 
-       /*
-        * last_timeout_jiffies is updated here to avoid
-        * smi_timeout() handler passing very large time_diff
-        * value to smi_event_handler() that causes
-        * the send command to abort.
-        */
-       smi_info->last_timeout_jiffies = jiffies;
-
-       mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
-
-       if (smi_info->thread)
-               wake_up_process(smi_info->thread);
-
        if (smi_info->run_to_completion) {
                /*
                 * If we are running to completion, then throw it in
@@ -924,16 +889,29 @@ static void sender(void                *send_info,
                return;
        }
 
-       spin_lock_irqsave(&smi_info->msg_lock, flags);
+       spin_lock_irqsave(&smi_info->si_lock, flags);
        if (priority > 0)
                list_add_tail(&msg->link, &smi_info->hp_xmit_msgs);
        else
                list_add_tail(&msg->link, &smi_info->xmit_msgs);
-       spin_unlock_irqrestore(&smi_info->msg_lock, flags);
 
-       spin_lock_irqsave(&smi_info->si_lock, flags);
-       if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL)
+       if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) {
+               /*
+                * last_timeout_jiffies is updated here to avoid
+                * smi_timeout() handler passing very large time_diff
+                * value to smi_event_handler() that causes
+                * the send command to abort.
+                */
+               smi_info->last_timeout_jiffies = jiffies;
+
+               mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+
+               if (smi_info->thread)
+                       wake_up_process(smi_info->thread);
+
                start_next_msg(smi_info);
+               smi_event_handler(smi_info, 0);
+       }
        spin_unlock_irqrestore(&smi_info->si_lock, flags);
 }
 
@@ -1034,16 +1012,19 @@ static int ipmi_thread(void *data)
 static void poll(void *send_info)
 {
        struct smi_info *smi_info = send_info;
-       unsigned long flags;
+       unsigned long flags = 0;
+       int run_to_completion = smi_info->run_to_completion;
 
        /*
         * Make sure there is some delay in the poll loop so we can
         * drive time forward and timeout things.
         */
        udelay(10);
-       spin_lock_irqsave(&smi_info->si_lock, flags);
+       if (!run_to_completion)
+               spin_lock_irqsave(&smi_info->si_lock, flags);
        smi_event_handler(smi_info, 10);
-       spin_unlock_irqrestore(&smi_info->si_lock, flags);
+       if (!run_to_completion)
+               spin_unlock_irqrestore(&smi_info->si_lock, flags);
 }
 
 static void request_events(void *send_info)
@@ -1680,10 +1661,8 @@ static struct smi_info *smi_info_alloc(void)
 {
        struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
 
-       if (info) {
+       if (info)
                spin_lock_init(&info->si_lock);
-               spin_lock_init(&info->msg_lock);
-       }
        return info;
 }
 
index 34767a6d7f42a354edca655d901c298e3883609a..7ed356e520351741173757d81270334e10ec4585 100644 (file)
 #endif
 
 static DEFINE_MUTEX(ipmi_watchdog_mutex);
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 static ipmi_user_t watchdog_user;
 static int watchdog_ifnum;
@@ -320,7 +320,7 @@ module_param(start_now, int, 0444);
 MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
                 "soon as the driver is loaded.");
 
-module_param(nowayout, int, 0644);
+module_param(nowayout, bool, 0644);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                 "(default=CONFIG_WATCHDOG_NOWAYOUT)");
 
@@ -520,6 +520,7 @@ static void panic_halt_ipmi_heartbeat(void)
        msg.cmd = IPMI_WDOG_RESET_TIMER;
        msg.data = NULL;
        msg.data_len = 0;
+       atomic_add(2, &panic_done_count);
        rv = ipmi_request_supply_msgs(watchdog_user,
                                      (struct ipmi_addr *) &addr,
                                      0,
@@ -528,8 +529,8 @@ static void panic_halt_ipmi_heartbeat(void)
                                      &panic_halt_heartbeat_smi_msg,
                                      &panic_halt_heartbeat_recv_msg,
                                      1);
-       if (!rv)
-               atomic_add(2, &panic_done_count);
+       if (rv)
+               atomic_sub(2, &panic_done_count);
 }
 
 static struct ipmi_smi_msg panic_halt_smi_msg = {
@@ -553,16 +554,18 @@ static void panic_halt_ipmi_set_timeout(void)
        /* Wait for the messages to be free. */
        while (atomic_read(&panic_done_count) != 0)
                ipmi_poll_interface(watchdog_user);
+       atomic_add(2, &panic_done_count);
        rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
                                &panic_halt_recv_msg,
                                &send_heartbeat_now);
-       if (!rv) {
-               atomic_add(2, &panic_done_count);
-               if (send_heartbeat_now)
-                       panic_halt_ipmi_heartbeat();
-       } else
+       if (rv) {
+               atomic_sub(2, &panic_done_count);
                printk(KERN_WARNING PFX
                       "Unable to extend the watchdog timeout.");
+       } else {
+               if (send_heartbeat_now)
+                       panic_halt_ipmi_heartbeat();
+       }
        while (atomic_read(&panic_done_count) != 0)
                ipmi_poll_interface(watchdog_user);
 }
@@ -1164,7 +1167,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
                if (code == SYS_POWER_OFF || code == SYS_HALT) {
                        /* Disable the WDT if we are shutting down. */
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
-                       panic_halt_ipmi_set_timeout();
+                       ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
                } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
                        /* Set a long timer to let the reboot happens, but
                           reboot if it hangs, but only if the watchdog
@@ -1172,7 +1175,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
                        timeout = 120;
                        pretimeout = 0;
                        ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
-                       panic_halt_ipmi_set_timeout();
+                       ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
                }
        }
        return NOTIFY_OK;
index f43485607063af7490ae37013de97675fbf156c5..a741e418b456d2fe966fda9b7175fc67d35c221c 100644 (file)
 
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
@@ -706,16 +705,13 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
 {
        unsigned int minor;
        struct timeval par_timeout;
-       struct compat_timeval __user *tc;
        int ret;
 
        minor = iminor(file->f_path.dentry->d_inode);
        mutex_lock(&lp_mutex);
        switch (cmd) {
        case LPSETTIMEOUT:
-               tc = compat_ptr(arg);
-               if (get_user(par_timeout.tv_sec, &tc->tv_sec) ||
-                   get_user(par_timeout.tv_usec, &tc->tv_usec)) {
+               if (compat_get_timeval(&par_timeout, compat_ptr(arg))) {
                        ret = -EFAULT;
                        break;
                }
index 1aeaaba680d22e1e943995efeff6b0ed671c5fe8..47ff7e470d87dc15cd0f8ba558b00c1e45e5ecbc 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/intr.h>
index 5c0d96a820fa02f545d8f575d9fd54771063935c..8b78750f1efe89d50a1ea075420ea032f4ad2ecd 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/slab.h>
 #include <linux/numa.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <linux/atomic.h>
 #include <asm/tlbflush.h>
index 492dbfb2efd678c0cc0798be8f70f054740b51b4..881c9e59593912261bd68a39b0c08cfbcd4b793d 100644 (file)
@@ -56,7 +56,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include "smapi.h"
 #include "mwavedd.h"
index eaade8a1ecd72df7eead2abf8838518d5bb0fbeb..9df78e2cc45d2951fc77815975cbeeb6633aea3a 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/mutex.h>
 
-#include <asm/system.h>
 
 static DEFINE_MUTEX(nvram_mutex);
 static DEFINE_SPINLOCK(nvram_state_lock);
index bf586ae1ee83cabad66a2029e0c540b74bee0370..d45c3345b4af4dae61f6458b5e14bc490c2a084e 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/io.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /*****************************************************************************/
index f6453df4921cb253c34bf854e923b0fc8680f7a4..0a484b4a1b02bdabfd231a2ed21b5446ccd95642 100644 (file)
@@ -60,7 +60,6 @@
 #include <linux/ioctl.h>
 #include <linux/synclink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index 872e09a02d239d7d32b92a26db00aad36fe16f67..af9437488b6c11353d1d0ff5737aecb7afff5c51 100644 (file)
@@ -83,7 +83,6 @@
 #include <linux/ratelimit.h>
 
 #include <asm/current.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_X86
 #include <asm/hpet.h>
index 1ee8ce7d27621699c235c5859bb7e9c0be4b5c53..45713f0e7d61adc208511a197691d2560557c489 100644 (file)
@@ -54,7 +54,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <linux/sonypi.h>
 
index e90e1c74fd4c1f61a006dc82dbfe481d38c84ceb..31ba11ca75e1bbca742dfb5c3ca9574a48101524 100644 (file)
@@ -89,7 +89,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_OF
 /* For open firmware. */
index 999d6a03e43689c4d82a14f80034aed452c95f38..5138927a416c99acdf13deed3e6d717a616a5af8 100644 (file)
@@ -26,7 +26,6 @@ config CLKSRC_DBX500_PRCMU
 config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
        bool "Clocksource PRCMU Timer sched_clock"
        depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
-       select HAVE_SCHED_CLOCK
        default y
        help
          Use the always on PRCMU Timer as sched_clock
index f5002015d82ea277c4e3e946a03e209a15f3eb64..a22ffa5bff9f85ca9ba961dc8896aa8be65c8fa3 100644 (file)
@@ -22,11 +22,11 @@ static struct cpufreq_frequency_table freq_table[] = {
        },
        [1] = {
                .index = 1,
-               .frequency = 300000,
+               .frequency = 400000,
        },
        [2] = {
                .index = 2,
-               .frequency = 600000,
+               .frequency = 800000,
        },
        [3] = {
                /* Used for MAX_OPP, if available */
@@ -113,12 +113,9 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 
        BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
 
-       if (!prcmu_is_u8400()) {
-               freq_table[1].frequency = 400000;
-               freq_table[2].frequency = 800000;
-               if (prcmu_has_arm_maxopp())
-                       freq_table[3].frequency = 1000000;
-       }
+       if (prcmu_has_arm_maxopp())
+               freq_table[3].frequency = 1000000;
+
        pr_info("db8500-cpufreq : Available frequencies:\n");
        for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
                pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
index 67bbb06d046081cd9d0f3786b7fdecd2b23ab955..17fa04d08be9cc0af181e5f20398128d8b4d5234 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
 
-#include <asm/system.h>
 #include <asm/smp_plat.h>
 #include <asm/cpu.h>
 
index cf7e1ee005a24c3d964dc6f8f1fd43c7b2fc4a33..334cc2f1e9f1fe1a675b7d9eadf9819fbedadfce 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <asm/timer.h>         /* Needed for recalibrate_cpu_khz() */
 #include <asm/msr.h>
-#include <asm/system.h>
 #include <asm/cpu_device_id.h>
 
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
index 4a6c46dea8a0c3c7741613576b5d9f180a2058c7..cf9da362d64f9a233512ce7a228bccad25906197 100644 (file)
@@ -201,7 +201,6 @@ config PL330_DMA
        tristate "DMA API Driver for PL330"
        select DMA_ENGINE
        depends on ARM_AMBA
-       select PL330
        help
          Select if your platform has one or more PL330 DMACs.
          You need to provide platform specific settings via
@@ -231,7 +230,7 @@ config IMX_SDMA
 
 config IMX_DMA
        tristate "i.MX DMA support"
-       depends on IMX_HAVE_DMA_V1
+       depends on ARCH_MXC
        select DMA_ENGINE
        help
          Support the i.MX DMA engine. This engine is integrated into
index 8a281584458b582bbb872137323ff82cdaac2eb1..c301a8ec31aa109583cd4ab54bc9304c3e95ceb2 100644 (file)
@@ -85,6 +85,8 @@
 #include <linux/slab.h>
 #include <asm/hardware/pl080.h>
 
+#include "dmaengine.h"
+
 #define DRIVER_NAME    "pl08xdmac"
 
 static struct amba_driver pl08x_amba_driver;
@@ -649,7 +651,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                        }
 
                        if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
-                                       (bd.srcbus.addr % bd.srcbus.buswidth)) {
+                                       (bd.dstbus.addr % bd.dstbus.buswidth)) {
                                dev_err(&pl08x->adev->dev,
                                        "%s src & dst address must be aligned to src"
                                        " & dst width if peripheral is flow controller",
@@ -919,13 +921,10 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
        struct pl08x_dma_chan *plchan = to_pl08x_chan(tx->chan);
        struct pl08x_txd *txd = to_pl08x_txd(tx);
        unsigned long flags;
+       dma_cookie_t cookie;
 
        spin_lock_irqsave(&plchan->lock, flags);
-
-       plchan->chan.cookie += 1;
-       if (plchan->chan.cookie < 0)
-               plchan->chan.cookie = 1;
-       tx->cookie = plchan->chan.cookie;
+       cookie = dma_cookie_assign(tx);
 
        /* Put this onto the pending list */
        list_add_tail(&txd->node, &plchan->pend_list);
@@ -945,7 +944,7 @@ static dma_cookie_t pl08x_tx_submit(struct dma_async_tx_descriptor *tx)
 
        spin_unlock_irqrestore(&plchan->lock, flags);
 
-       return tx->cookie;
+       return cookie;
 }
 
 static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt(
@@ -965,31 +964,17 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
                dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
        enum dma_status ret;
-       u32 bytesleft = 0;
 
-       last_used = plchan->chan.cookie;
-       last_complete = plchan->lc;
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
-       if (ret == DMA_SUCCESS) {
-               dma_set_tx_state(txstate, last_complete, last_used, 0);
+       ret = dma_cookie_status(chan, cookie, txstate);
+       if (ret == DMA_SUCCESS)
                return ret;
-       }
 
        /*
         * This cookie not complete yet
+        * Get number of bytes left in the active transactions and queue
         */
-       last_used = plchan->chan.cookie;
-       last_complete = plchan->lc;
-
-       /* Get number of bytes left in the active transactions and queue */
-       bytesleft = pl08x_getbytes_chan(plchan);
-
-       dma_set_tx_state(txstate, last_complete, last_used,
-                        bytesleft);
+       dma_set_residue(txstate, pl08x_getbytes_chan(plchan));
 
        if (plchan->state == PL08X_CHAN_PAUSED)
                return DMA_PAUSED;
@@ -1139,6 +1124,8 @@ static int dma_set_runtime_config(struct dma_chan *chan,
        cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT;
        cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT;
 
+       plchan->device_fc = config->device_fc;
+
        if (plchan->runtime_direction == DMA_DEV_TO_MEM) {
                plchan->src_addr = config->src_addr;
                plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR |
@@ -1326,7 +1313,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
 static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags)
+               unsigned long flags, void *context)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        struct pl08x_driver_data *pl08x = plchan->host;
@@ -1370,7 +1357,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
                return NULL;
        }
 
-       if (plchan->cd->device_fc)
+       if (plchan->device_fc)
                tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER_PER :
                        PL080_FLOW_PER2MEM_PER;
        else
@@ -1541,7 +1528,7 @@ static void pl08x_tasklet(unsigned long data)
 
        if (txd) {
                /* Update last completed */
-               plchan->lc = txd->tx.cookie;
+               dma_cookie_complete(&txd->tx);
        }
 
        /* If a new descriptor is queued, set it up plchan->at is NULL here */
@@ -1722,8 +1709,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                         chan->name);
 
                chan->chan.device = dmadev;
-               chan->chan.cookie = 0;
-               chan->lc = 0;
+               dma_cookie_init(&chan->chan);
 
                spin_lock_init(&chan->lock);
                INIT_LIST_HEAD(&chan->pend_list);
index f4aed5fc2cb6c33d87d8932d8603f705d3d2e589..7aa58d2048923721d7448464120515137ecc961f 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/of_device.h>
 
 #include "at_hdmac_regs.h"
+#include "dmaengine.h"
 
 /*
  * Glossary
@@ -191,27 +192,6 @@ static void atc_desc_chain(struct at_desc **first, struct at_desc **prev,
        *prev = desc;
 }
 
-/**
- * atc_assign_cookie - compute and assign new cookie
- * @atchan: channel we work on
- * @desc: descriptor to assign cookie for
- *
- * Called with atchan->lock held and bh disabled
- */
-static dma_cookie_t
-atc_assign_cookie(struct at_dma_chan *atchan, struct at_desc *desc)
-{
-       dma_cookie_t cookie = atchan->chan_common.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       atchan->chan_common.cookie = cookie;
-       desc->txd.cookie = cookie;
-
-       return cookie;
-}
-
 /**
  * atc_dostart - starts the DMA engine for real
  * @atchan: the channel we want to start
@@ -269,7 +249,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
        dev_vdbg(chan2dev(&atchan->chan_common),
                "descriptor %u complete\n", txd->cookie);
 
-       atchan->completed_cookie = txd->cookie;
+       dma_cookie_complete(txd);
 
        /* move children to free_list */
        list_splice_init(&desc->tx_list, &atchan->free_list);
@@ -547,7 +527,7 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
        unsigned long           flags;
 
        spin_lock_irqsave(&atchan->lock, flags);
-       cookie = atc_assign_cookie(atchan, desc);
+       cookie = dma_cookie_assign(tx);
 
        if (list_empty(&atchan->active_list)) {
                dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
@@ -659,14 +639,16 @@ err_desc_get:
  * @sg_len: number of entries in @scatterlist
  * @direction: DMA direction
  * @flags: tx descriptor status flags
+ * @context: transaction context (ignored)
  */
 static struct dma_async_tx_descriptor *
 atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags)
+               unsigned long flags, void *context)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma_slave     *atslave = chan->private;
+       struct dma_slave_config *sconfig = &atchan->dma_sconfig;
        struct at_desc          *first = NULL;
        struct at_desc          *prev = NULL;
        u32                     ctrla;
@@ -688,19 +670,18 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                return NULL;
        }
 
-       reg_width = atslave->reg_width;
-
        ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla;
        ctrlb = ATC_IEN;
 
        switch (direction) {
        case DMA_MEM_TO_DEV:
+               reg_width = convert_buswidth(sconfig->dst_addr_width);
                ctrla |=  ATC_DST_WIDTH(reg_width);
                ctrlb |=  ATC_DST_ADDR_MODE_FIXED
                        | ATC_SRC_ADDR_MODE_INCR
                        | ATC_FC_MEM2PER
                        | ATC_SIF(AT_DMA_MEM_IF) | ATC_DIF(AT_DMA_PER_IF);
-               reg = atslave->tx_reg;
+               reg = sconfig->dst_addr;
                for_each_sg(sgl, sg, sg_len, i) {
                        struct at_desc  *desc;
                        u32             len;
@@ -728,13 +709,14 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                }
                break;
        case DMA_DEV_TO_MEM:
+               reg_width = convert_buswidth(sconfig->src_addr_width);
                ctrla |=  ATC_SRC_WIDTH(reg_width);
                ctrlb |=  ATC_DST_ADDR_MODE_INCR
                        | ATC_SRC_ADDR_MODE_FIXED
                        | ATC_FC_PER2MEM
                        | ATC_SIF(AT_DMA_PER_IF) | ATC_DIF(AT_DMA_MEM_IF);
 
-               reg = atslave->rx_reg;
+               reg = sconfig->src_addr;
                for_each_sg(sgl, sg, sg_len, i) {
                        struct at_desc  *desc;
                        u32             len;
@@ -810,12 +792,15 @@ err_out:
  * atc_dma_cyclic_fill_desc - Fill one period decriptor
  */
 static int
-atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
+atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
                unsigned int period_index, dma_addr_t buf_addr,
-               size_t period_len, enum dma_transfer_direction direction)
+               unsigned int reg_width, size_t period_len,
+               enum dma_transfer_direction direction)
 {
-       u32             ctrla;
-       unsigned int    reg_width = atslave->reg_width;
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_dma_slave     *atslave = chan->private;
+       struct dma_slave_config *sconfig = &atchan->dma_sconfig;
+       u32                     ctrla;
 
        /* prepare common CRTLA value */
        ctrla =   ATC_DEFAULT_CTRLA | atslave->ctrla
@@ -826,7 +811,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
        switch (direction) {
        case DMA_MEM_TO_DEV:
                desc->lli.saddr = buf_addr + (period_len * period_index);
-               desc->lli.daddr = atslave->tx_reg;
+               desc->lli.daddr = sconfig->dst_addr;
                desc->lli.ctrla = ctrla;
                desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED
                                | ATC_SRC_ADDR_MODE_INCR
@@ -836,7 +821,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
                break;
 
        case DMA_DEV_TO_MEM:
-               desc->lli.saddr = atslave->rx_reg;
+               desc->lli.saddr = sconfig->src_addr;
                desc->lli.daddr = buf_addr + (period_len * period_index);
                desc->lli.ctrla = ctrla;
                desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR
@@ -860,16 +845,20 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
  * @buf_len: total number of bytes for the entire buffer
  * @period_len: number of bytes for each period
  * @direction: transfer direction, to or from device
+ * @context: transfer context (ignored)
  */
 static struct dma_async_tx_descriptor *
 atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-               size_t period_len, enum dma_transfer_direction direction)
+               size_t period_len, enum dma_transfer_direction direction,
+               void *context)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma_slave     *atslave = chan->private;
+       struct dma_slave_config *sconfig = &atchan->dma_sconfig;
        struct at_desc          *first = NULL;
        struct at_desc          *prev = NULL;
        unsigned long           was_cyclic;
+       unsigned int            reg_width;
        unsigned int            periods = buf_len / period_len;
        unsigned int            i;
 
@@ -889,8 +878,13 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
                return NULL;
        }
 
+       if (sconfig->direction == DMA_MEM_TO_DEV)
+               reg_width = convert_buswidth(sconfig->dst_addr_width);
+       else
+               reg_width = convert_buswidth(sconfig->src_addr_width);
+
        /* Check for too big/unaligned periods and unaligned DMA buffer */
-       if (atc_dma_cyclic_check_values(atslave->reg_width, buf_addr,
+       if (atc_dma_cyclic_check_values(reg_width, buf_addr,
                                        period_len, direction))
                goto err_out;
 
@@ -902,8 +896,8 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
                if (!desc)
                        goto err_desc_get;
 
-               if (atc_dma_cyclic_fill_desc(atslave, desc, i, buf_addr,
-                                               period_len, direction))
+               if (atc_dma_cyclic_fill_desc(chan, desc, i, buf_addr,
+                                            reg_width, period_len, direction))
                        goto err_desc_get;
 
                atc_desc_chain(&first, &prev, desc);
@@ -926,6 +920,23 @@ err_out:
        return NULL;
 }
 
+static int set_runtime_config(struct dma_chan *chan,
+                             struct dma_slave_config *sconfig)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+
+       /* Check if it is chan is configured for slave transfers */
+       if (!chan->private)
+               return -EINVAL;
+
+       memcpy(&atchan->dma_sconfig, sconfig, sizeof(*sconfig));
+
+       convert_burst(&atchan->dma_sconfig.src_maxburst);
+       convert_burst(&atchan->dma_sconfig.dst_maxburst);
+
+       return 0;
+}
+
 
 static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                       unsigned long arg)
@@ -986,6 +997,8 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                clear_bit(ATC_IS_CYCLIC, &atchan->status);
 
                spin_unlock_irqrestore(&atchan->lock, flags);
+       } else if (cmd == DMA_SLAVE_CONFIG) {
+               return set_runtime_config(chan, (struct dma_slave_config *)arg);
        } else {
                return -ENXIO;
        }
@@ -1016,26 +1029,20 @@ atc_tx_status(struct dma_chan *chan,
 
        spin_lock_irqsave(&atchan->lock, flags);
 
-       last_complete = atchan->completed_cookie;
-       last_used = chan->cookie;
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret != DMA_SUCCESS) {
                atc_cleanup_descriptors(atchan);
 
-               last_complete = atchan->completed_cookie;
-               last_used = chan->cookie;
-
-               ret = dma_async_is_complete(cookie, last_complete, last_used);
+               ret = dma_cookie_status(chan, cookie, txstate);
        }
 
+       last_complete = chan->completed_cookie;
+       last_used = chan->cookie;
+
        spin_unlock_irqrestore(&atchan->lock, flags);
 
        if (ret != DMA_SUCCESS)
-               dma_set_tx_state(txstate, last_complete, last_used,
-                       atc_first_active(atchan)->len);
-       else
-               dma_set_tx_state(txstate, last_complete, last_used, 0);
+               dma_set_residue(txstate, atc_first_active(atchan)->len);
 
        if (atc_chan_is_paused(atchan))
                ret = DMA_PAUSED;
@@ -1129,7 +1136,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
        spin_lock_irqsave(&atchan->lock, flags);
        atchan->descs_allocated = i;
        list_splice(&tmp_list, &atchan->free_list);
-       atchan->completed_cookie = chan->cookie = 1;
+       dma_cookie_init(chan);
        spin_unlock_irqrestore(&atchan->lock, flags);
 
        /* channel parameters */
@@ -1329,7 +1336,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
                struct at_dma_chan      *atchan = &atdma->chan[i];
 
                atchan->chan_common.device = &atdma->dma_common;
-               atchan->chan_common.cookie = atchan->completed_cookie = 1;
+               dma_cookie_init(&atchan->chan_common);
                list_add_tail(&atchan->chan_common.device_node,
                                &atdma->dma_common.channels);
 
index a8d3277d60b5cdd238ea77959c7b40185edfc077..897a8bcaec90d288003b3ee89d631b620d197935 100644 (file)
@@ -207,8 +207,8 @@ enum atc_status {
  * @save_cfg: configuration register that is saved on suspend/resume cycle
  * @save_dscr: for cyclic operations, preserve next descriptor address in
  *             the cyclic list on suspend/resume cycle
+ * @dma_sconfig: configuration for slave transfers, passed via DMA_SLAVE_CONFIG
  * @lock: serializes enqueue/dequeue operations to descriptors lists
- * @completed_cookie: identifier for the most recently completed operation
  * @active_list: list of descriptors dmaengine is being running on
  * @queue: list of descriptors ready to be submitted to engine
  * @free_list: list of descriptors usable by the channel
@@ -223,11 +223,11 @@ struct at_dma_chan {
        struct tasklet_struct   tasklet;
        u32                     save_cfg;
        u32                     save_dscr;
+       struct dma_slave_config dma_sconfig;
 
        spinlock_t              lock;
 
        /* these other elements are all protected by lock */
-       dma_cookie_t            completed_cookie;
        struct list_head        active_list;
        struct list_head        queue;
        struct list_head        free_list;
@@ -245,6 +245,36 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
        return container_of(dchan, struct at_dma_chan, chan_common);
 }
 
+/*
+ * Fix sconfig's burst size according to at_hdmac. We need to convert them as:
+ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3, 32 -> 4, 64 -> 5, 128 -> 6, 256 -> 7.
+ *
+ * This can be done by finding most significant bit set.
+ */
+static inline void convert_burst(u32 *maxburst)
+{
+       if (*maxburst > 1)
+               *maxburst = fls(*maxburst) - 2;
+       else
+               *maxburst = 0;
+}
+
+/*
+ * Fix sconfig's bus width according to at_hdmac.
+ * 1 byte -> 0, 2 bytes -> 1, 4 bytes -> 2.
+ */
+static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width)
+{
+       switch (addr_width) {
+       case DMA_SLAVE_BUSWIDTH_2_BYTES:
+               return 1;
+       case DMA_SLAVE_BUSWIDTH_4_BYTES:
+               return 2;
+       default:
+               /* For 1 byte width or fallback */
+               return 0;
+       }
+}
 
 /*--  Controller  ------------------------------------------------------*/
 
index d65a718c0f9b1ae5819aef9af4c1c58200627a22..dc89455f5550c90ffec150d16f3d0e06e5614ee0 100644 (file)
@@ -24,6 +24,7 @@
 #include <mach/coh901318.h>
 
 #include "coh901318_lli.h"
+#include "dmaengine.h"
 
 #define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
 
@@ -59,7 +60,6 @@ struct coh901318_base {
 struct coh901318_chan {
        spinlock_t lock;
        int allocated;
-       int completed;
        int id;
        int stopped;
 
@@ -318,20 +318,6 @@ static int coh901318_prep_linked_list(struct coh901318_chan *cohc,
 
        return 0;
 }
-static dma_cookie_t
-coh901318_assign_cookie(struct coh901318_chan *cohc,
-                       struct coh901318_desc *cohd)
-{
-       dma_cookie_t cookie = cohc->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       cohc->chan.cookie = cookie;
-       cohd->desc.cookie = cookie;
-
-       return cookie;
-}
 
 static struct coh901318_desc *
 coh901318_desc_get(struct coh901318_chan *cohc)
@@ -705,7 +691,7 @@ static void dma_tasklet(unsigned long data)
        callback_param = cohd_fin->desc.callback_param;
 
        /* sign this job as completed on the channel */
-       cohc->completed = cohd_fin->desc.cookie;
+       dma_cookie_complete(&cohd_fin->desc);
 
        /* release the lli allocation and remove the descriptor */
        coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli);
@@ -929,7 +915,7 @@ static int coh901318_alloc_chan_resources(struct dma_chan *chan)
        coh901318_config(cohc, NULL);
 
        cohc->allocated = 1;
-       cohc->completed = chan->cookie = 1;
+       dma_cookie_init(chan);
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 
@@ -966,16 +952,16 @@ coh901318_tx_submit(struct dma_async_tx_descriptor *tx)
                                                   desc);
        struct coh901318_chan *cohc = to_coh901318_chan(tx->chan);
        unsigned long flags;
+       dma_cookie_t cookie;
 
        spin_lock_irqsave(&cohc->lock, flags);
-
-       tx->cookie = coh901318_assign_cookie(cohc, cohd);
+       cookie = dma_cookie_assign(tx);
 
        coh901318_desc_queue(cohc, cohd);
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 
-       return tx->cookie;
+       return cookie;
 }
 
 static struct dma_async_tx_descriptor *
@@ -1035,7 +1021,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 static struct dma_async_tx_descriptor *
 coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        unsigned int sg_len, enum dma_transfer_direction direction,
-                       unsigned long flags)
+                       unsigned long flags, void *context)
 {
        struct coh901318_chan *cohc = to_coh901318_chan(chan);
        struct coh901318_lli *lli;
@@ -1165,17 +1151,12 @@ coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                 struct dma_tx_state *txstate)
 {
        struct coh901318_chan *cohc = to_coh901318_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
-       int ret;
-
-       last_complete = cohc->completed;
-       last_used = chan->cookie;
+       enum dma_status ret;
 
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
+       /* FIXME: should be conditional on ret != DMA_SUCCESS? */
+       dma_set_residue(txstate, coh901318_get_bytes_left(chan));
 
-       dma_set_tx_state(txstate, last_complete, last_used,
-                        coh901318_get_bytes_left(chan));
        if (ret == DMA_IN_PROGRESS && cohc->stopped)
                ret = DMA_PAUSED;
 
index a6c6051ec85811041277c64d675810f14d9da851..767bcc31b3653b7813a9acbde71f2fcd1f3a0130 100644 (file)
@@ -510,8 +510,8 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
                                         dma_chan_name(chan));
                                list_del_rcu(&device->global_node);
                        } else if (err)
-                               pr_debug("dmaengine: failed to get %s: (%d)\n",
-                                        dma_chan_name(chan), err);
+                               pr_debug("%s: failed to get %s: (%d)\n",
+                                       __func__, dma_chan_name(chan), err);
                        else
                                break;
                        if (--device->privatecnt == 0)
@@ -564,8 +564,8 @@ void dmaengine_get(void)
                                list_del_rcu(&device->global_node);
                                break;
                        } else if (err)
-                               pr_err("dmaengine: failed to get %s: (%d)\n",
-                                      dma_chan_name(chan), err);
+                               pr_err("%s: failed to get %s: (%d)\n",
+                                       __func__, dma_chan_name(chan), err);
                }
        }
 
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
new file mode 100644 (file)
index 0000000..17f983a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * The contents of this file are private to DMA engine drivers, and is not
+ * part of the API to be used by DMA engine users.
+ */
+#ifndef DMAENGINE_H
+#define DMAENGINE_H
+
+#include <linux/bug.h>
+#include <linux/dmaengine.h>
+
+/**
+ * dma_cookie_init - initialize the cookies for a DMA channel
+ * @chan: dma channel to initialize
+ */
+static inline void dma_cookie_init(struct dma_chan *chan)
+{
+       chan->cookie = DMA_MIN_COOKIE;
+       chan->completed_cookie = DMA_MIN_COOKIE;
+}
+
+/**
+ * dma_cookie_assign - assign a DMA engine cookie to the descriptor
+ * @tx: descriptor needing cookie
+ *
+ * Assign a unique non-zero per-channel cookie to the descriptor.
+ * Note: caller is expected to hold a lock to prevent concurrency.
+ */
+static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx)
+{
+       struct dma_chan *chan = tx->chan;
+       dma_cookie_t cookie;
+
+       cookie = chan->cookie + 1;
+       if (cookie < DMA_MIN_COOKIE)
+               cookie = DMA_MIN_COOKIE;
+       tx->cookie = chan->cookie = cookie;
+
+       return cookie;
+}
+
+/**
+ * dma_cookie_complete - complete a descriptor
+ * @tx: descriptor to complete
+ *
+ * Mark this descriptor complete by updating the channels completed
+ * cookie marker.  Zero the descriptors cookie to prevent accidental
+ * repeated completions.
+ *
+ * Note: caller is expected to hold a lock to prevent concurrency.
+ */
+static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx)
+{
+       BUG_ON(tx->cookie < DMA_MIN_COOKIE);
+       tx->chan->completed_cookie = tx->cookie;
+       tx->cookie = 0;
+}
+
+/**
+ * dma_cookie_status - report cookie status
+ * @chan: dma channel
+ * @cookie: cookie we are interested in
+ * @state: dma_tx_state structure to return last/used cookies
+ *
+ * Report the status of the cookie, filling in the state structure if
+ * non-NULL.  No locking is required.
+ */
+static inline enum dma_status dma_cookie_status(struct dma_chan *chan,
+       dma_cookie_t cookie, struct dma_tx_state *state)
+{
+       dma_cookie_t used, complete;
+
+       used = chan->cookie;
+       complete = chan->completed_cookie;
+       barrier();
+       if (state) {
+               state->last = complete;
+               state->used = used;
+               state->residue = 0;
+       }
+       return dma_async_is_complete(cookie, complete, used);
+}
+
+static inline void dma_set_residue(struct dma_tx_state *state, u32 residue)
+{
+       if (state)
+               state->residue = residue;
+}
+
+#endif
index 9b592b02b5f49a3023cdc883322af7c451448a0a..7439079f5eed9c58bc9d39e0fc92795e29adc7dd 100644 (file)
@@ -9,6 +9,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/dmaengine.h>
@@ -22,6 +23,7 @@
 #include <linux/slab.h>
 
 #include "dw_dmac_regs.h"
+#include "dmaengine.h"
 
 /*
  * This supports the Synopsys "DesignWare AHB Central DMA Controller",
  * which does not support descriptor writeback.
  */
 
-#define DWC_DEFAULT_CTLLO(private) ({                          \
-               struct dw_dma_slave *__slave = (private);       \
-               int dms = __slave ? __slave->dst_master : 0;    \
-               int sms = __slave ? __slave->src_master : 1;    \
-               u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \
-               u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \
+#define DWC_DEFAULT_CTLLO(_chan) ({                            \
+               struct dw_dma_slave *__slave = (_chan->private);        \
+               struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan);       \
+               struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \
+               int _dms = __slave ? __slave->dst_master : 0;   \
+               int _sms = __slave ? __slave->src_master : 1;   \
+               u8 _smsize = __slave ? _sconfig->src_maxburst : \
+                       DW_DMA_MSIZE_16;                        \
+               u8 _dmsize = __slave ? _sconfig->dst_maxburst : \
+                       DW_DMA_MSIZE_16;                        \
                                                                \
-               (DWC_CTLL_DST_MSIZE(dmsize)                     \
-                | DWC_CTLL_SRC_MSIZE(smsize)                   \
+               (DWC_CTLL_DST_MSIZE(_dmsize)                    \
+                | DWC_CTLL_SRC_MSIZE(_smsize)                  \
                 | DWC_CTLL_LLP_D_EN                            \
                 | DWC_CTLL_LLP_S_EN                            \
-                | DWC_CTLL_DMS(dms)                            \
-                | DWC_CTLL_SMS(sms));                          \
+                | DWC_CTLL_DMS(_dms)                           \
+                | DWC_CTLL_SMS(_sms));                         \
        })
 
 /*
@@ -151,21 +157,6 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
        }
 }
 
-/* Called with dwc->lock held and bh disabled */
-static dma_cookie_t
-dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
-{
-       dma_cookie_t cookie = dwc->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       dwc->chan.cookie = cookie;
-       desc->txd.cookie = cookie;
-
-       return cookie;
-}
-
 static void dwc_initialize(struct dw_dma_chan *dwc)
 {
        struct dw_dma *dw = to_dw_dma(dwc->chan.device);
@@ -192,7 +183,6 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 
        /* Enable interrupts */
        channel_set_bit(dw, MASK.XFER, dwc->mask);
-       channel_set_bit(dw, MASK.BLOCK, dwc->mask);
        channel_set_bit(dw, MASK.ERROR, dwc->mask);
 
        dwc->initialized = true;
@@ -245,7 +235,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
        dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
 
        spin_lock_irqsave(&dwc->lock, flags);
-       dwc->completed = txd->cookie;
+       dma_cookie_complete(txd);
        if (callback_required) {
                callback = txd->callback;
                param = txd->callback_param;
@@ -329,12 +319,6 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
        unsigned long flags;
 
        spin_lock_irqsave(&dwc->lock, flags);
-       /*
-        * Clear block interrupt flag before scanning so that we don't
-        * miss any, and read LLP before RAW_XFER to ensure it is
-        * valid if we decide to scan the list.
-        */
-       dma_writel(dw, CLEAR.BLOCK, dwc->mask);
        llp = channel_readl(dwc, LLP);
        status_xfer = dma_readl(dw, RAW.XFER);
 
@@ -470,17 +454,16 @@ EXPORT_SYMBOL(dw_dma_get_dst_addr);
 
 /* called with dwc->lock held and all DMAC interrupts disabled */
 static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
-               u32 status_block, u32 status_err, u32 status_xfer)
+               u32 status_err, u32 status_xfer)
 {
        unsigned long flags;
 
-       if (status_block & dwc->mask) {
+       if (dwc->mask) {
                void (*callback)(void *param);
                void *callback_param;
 
                dev_vdbg(chan2dev(&dwc->chan), "new cyclic period llp 0x%08x\n",
                                channel_readl(dwc, LLP));
-               dma_writel(dw, CLEAR.BLOCK, dwc->mask);
 
                callback = dwc->cdesc->period_callback;
                callback_param = dwc->cdesc->period_callback_param;
@@ -520,7 +503,6 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
                channel_writel(dwc, CTL_LO, 0);
                channel_writel(dwc, CTL_HI, 0);
 
-               dma_writel(dw, CLEAR.BLOCK, dwc->mask);
                dma_writel(dw, CLEAR.ERROR, dwc->mask);
                dma_writel(dw, CLEAR.XFER, dwc->mask);
 
@@ -537,36 +519,29 @@ static void dw_dma_tasklet(unsigned long data)
 {
        struct dw_dma *dw = (struct dw_dma *)data;
        struct dw_dma_chan *dwc;
-       u32 status_block;
        u32 status_xfer;
        u32 status_err;
        int i;
 
-       status_block = dma_readl(dw, RAW.BLOCK);
        status_xfer = dma_readl(dw, RAW.XFER);
        status_err = dma_readl(dw, RAW.ERROR);
 
-       dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
-                       status_block, status_err);
+       dev_vdbg(dw->dma.dev, "tasklet: status_err=%x\n", status_err);
 
        for (i = 0; i < dw->dma.chancnt; i++) {
                dwc = &dw->chan[i];
                if (test_bit(DW_DMA_IS_CYCLIC, &dwc->flags))
-                       dwc_handle_cyclic(dw, dwc, status_block, status_err,
-                                       status_xfer);
+                       dwc_handle_cyclic(dw, dwc, status_err, status_xfer);
                else if (status_err & (1 << i))
                        dwc_handle_error(dw, dwc);
-               else if ((status_block | status_xfer) & (1 << i))
+               else if (status_xfer & (1 << i))
                        dwc_scan_descriptors(dw, dwc);
        }
 
        /*
-        * Re-enable interrupts. Block Complete interrupts are only
-        * enabled if the INT_EN bit in the descriptor is set. This
-        * will trigger a scan before the whole list is done.
+        * Re-enable interrupts.
         */
        channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
-       channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
        channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
 }
 
@@ -583,7 +558,6 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
         * softirq handler.
         */
        channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
-       channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
 
        status = dma_readl(dw, STATUS_INT);
@@ -594,7 +568,6 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
 
                /* Try to recover */
                channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1);
-               channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1);
                channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1);
                channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1);
                channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1);
@@ -615,7 +588,7 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
        unsigned long           flags;
 
        spin_lock_irqsave(&dwc->lock, flags);
-       cookie = dwc_assign_cookie(dwc, desc);
+       cookie = dma_cookie_assign(tx);
 
        /*
         * REVISIT: We should attempt to chain as many descriptors as
@@ -674,7 +647,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
        else
                src_width = dst_width = 0;
 
-       ctllo = DWC_DEFAULT_CTLLO(chan->private)
+       ctllo = DWC_DEFAULT_CTLLO(chan)
                        | DWC_CTLL_DST_WIDTH(dst_width)
                        | DWC_CTLL_SRC_WIDTH(src_width)
                        | DWC_CTLL_DST_INC
@@ -731,10 +704,11 @@ err_desc_get:
 static struct dma_async_tx_descriptor *
 dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags)
+               unsigned long flags, void *context)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
        struct dw_dma_slave     *dws = chan->private;
+       struct dma_slave_config *sconfig = &dwc->dma_sconfig;
        struct dw_desc          *prev;
        struct dw_desc          *first;
        u32                     ctllo;
@@ -750,25 +724,34 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        if (unlikely(!dws || !sg_len))
                return NULL;
 
-       reg_width = dws->reg_width;
        prev = first = NULL;
 
        switch (direction) {
        case DMA_MEM_TO_DEV:
-               ctllo = (DWC_DEFAULT_CTLLO(chan->private)
+               reg_width = __fls(sconfig->dst_addr_width);
+               reg = sconfig->dst_addr;
+               ctllo = (DWC_DEFAULT_CTLLO(chan)
                                | DWC_CTLL_DST_WIDTH(reg_width)
                                | DWC_CTLL_DST_FIX
-                               | DWC_CTLL_SRC_INC
-                               | DWC_CTLL_FC(dws->fc));
-               reg = dws->tx_reg;
+                               | DWC_CTLL_SRC_INC);
+
+               ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
+                       DWC_CTLL_FC(DW_DMA_FC_D_M2P);
+
                for_each_sg(sgl, sg, sg_len, i) {
                        struct dw_desc  *desc;
                        u32             len, dlen, mem;
 
                        mem = sg_phys(sg);
                        len = sg_dma_len(sg);
-                       mem_width = 2;
-                       if (unlikely(mem & 3 || len & 3))
+
+                       if (!((mem | len) & 7))
+                               mem_width = 3;
+                       else if (!((mem | len) & 3))
+                               mem_width = 2;
+                       else if (!((mem | len) & 1))
+                               mem_width = 1;
+                       else
                                mem_width = 0;
 
 slave_sg_todev_fill_desc:
@@ -812,21 +795,30 @@ slave_sg_todev_fill_desc:
                }
                break;
        case DMA_DEV_TO_MEM:
-               ctllo = (DWC_DEFAULT_CTLLO(chan->private)
+               reg_width = __fls(sconfig->src_addr_width);
+               reg = sconfig->src_addr;
+               ctllo = (DWC_DEFAULT_CTLLO(chan)
                                | DWC_CTLL_SRC_WIDTH(reg_width)
                                | DWC_CTLL_DST_INC
-                               | DWC_CTLL_SRC_FIX
-                               | DWC_CTLL_FC(dws->fc));
+                               | DWC_CTLL_SRC_FIX);
+
+               ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
+                       DWC_CTLL_FC(DW_DMA_FC_D_P2M);
 
-               reg = dws->rx_reg;
                for_each_sg(sgl, sg, sg_len, i) {
                        struct dw_desc  *desc;
                        u32             len, dlen, mem;
 
                        mem = sg_phys(sg);
                        len = sg_dma_len(sg);
-                       mem_width = 2;
-                       if (unlikely(mem & 3 || len & 3))
+
+                       if (!((mem | len) & 7))
+                               mem_width = 3;
+                       else if (!((mem | len) & 3))
+                               mem_width = 2;
+                       else if (!((mem | len) & 1))
+                               mem_width = 1;
+                       else
                                mem_width = 0;
 
 slave_sg_fromdev_fill_desc:
@@ -890,6 +882,39 @@ err_desc_get:
        return NULL;
 }
 
+/*
+ * Fix sconfig's burst size according to dw_dmac. We need to convert them as:
+ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
+ *
+ * NOTE: burst size 2 is not supported by controller.
+ *
+ * This can be done by finding least significant bit set: n & (n - 1)
+ */
+static inline void convert_burst(u32 *maxburst)
+{
+       if (*maxburst > 1)
+               *maxburst = fls(*maxburst) - 2;
+       else
+               *maxburst = 0;
+}
+
+static int
+set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
+{
+       struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+
+       /* Check if it is chan is configured for slave transfers */
+       if (!chan->private)
+               return -EINVAL;
+
+       memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
+
+       convert_burst(&dwc->dma_sconfig.src_maxburst);
+       convert_burst(&dwc->dma_sconfig.dst_maxburst);
+
+       return 0;
+}
+
 static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                       unsigned long arg)
 {
@@ -939,8 +964,11 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                /* Flush all pending and queued descriptors */
                list_for_each_entry_safe(desc, _desc, &list, desc_node)
                        dwc_descriptor_complete(dwc, desc, false);
-       } else
+       } else if (cmd == DMA_SLAVE_CONFIG) {
+               return set_runtime_config(chan, (struct dma_slave_config *)arg);
+       } else {
                return -ENXIO;
+       }
 
        return 0;
 }
@@ -951,28 +979,17 @@ dwc_tx_status(struct dma_chan *chan,
              struct dma_tx_state *txstate)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
-       dma_cookie_t            last_used;
-       dma_cookie_t            last_complete;
-       int                     ret;
-
-       last_complete = dwc->completed;
-       last_used = chan->cookie;
+       enum dma_status         ret;
 
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret != DMA_SUCCESS) {
                dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
 
-               last_complete = dwc->completed;
-               last_used = chan->cookie;
-
-               ret = dma_async_is_complete(cookie, last_complete, last_used);
+               ret = dma_cookie_status(chan, cookie, txstate);
        }
 
        if (ret != DMA_SUCCESS)
-               dma_set_tx_state(txstate, last_complete, last_used,
-                               dwc_first_active(dwc)->len);
-       else
-               dma_set_tx_state(txstate, last_complete, last_used, 0);
+               dma_set_residue(txstate, dwc_first_active(dwc)->len);
 
        if (dwc->paused)
                return DMA_PAUSED;
@@ -1004,7 +1021,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
                return -EIO;
        }
 
-       dwc->completed = chan->cookie = 1;
+       dma_cookie_init(chan);
 
        /*
         * NOTE: some controllers may have additional features that we
@@ -1068,7 +1085,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 
        /* Disable interrupts */
        channel_clear_bit(dw, MASK.XFER, dwc->mask);
-       channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
        channel_clear_bit(dw, MASK.ERROR, dwc->mask);
 
        spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1120,7 +1136,6 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
                return -EBUSY;
        }
 
-       dma_writel(dw, CLEAR.BLOCK, dwc->mask);
        dma_writel(dw, CLEAR.ERROR, dwc->mask);
        dma_writel(dw, CLEAR.XFER, dwc->mask);
 
@@ -1175,11 +1190,11 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
                enum dma_transfer_direction direction)
 {
        struct dw_dma_chan              *dwc = to_dw_dma_chan(chan);
+       struct dma_slave_config         *sconfig = &dwc->dma_sconfig;
        struct dw_cyclic_desc           *cdesc;
        struct dw_cyclic_desc           *retval = NULL;
        struct dw_desc                  *desc;
        struct dw_desc                  *last = NULL;
-       struct dw_dma_slave             *dws = chan->private;
        unsigned long                   was_cyclic;
        unsigned int                    reg_width;
        unsigned int                    periods;
@@ -1203,7 +1218,12 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
        }
 
        retval = ERR_PTR(-EINVAL);
-       reg_width = dws->reg_width;
+
+       if (direction == DMA_MEM_TO_DEV)
+               reg_width = __ffs(sconfig->dst_addr_width);
+       else
+               reg_width = __ffs(sconfig->src_addr_width);
+
        periods = buf_len / period_len;
 
        /* Check for too big/unaligned periods and unaligned DMA buffer. */
@@ -1236,26 +1256,34 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
 
                switch (direction) {
                case DMA_MEM_TO_DEV:
-                       desc->lli.dar = dws->tx_reg;
+                       desc->lli.dar = sconfig->dst_addr;
                        desc->lli.sar = buf_addr + (period_len * i);
-                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
+                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan)
                                        | DWC_CTLL_DST_WIDTH(reg_width)
                                        | DWC_CTLL_SRC_WIDTH(reg_width)
                                        | DWC_CTLL_DST_FIX
                                        | DWC_CTLL_SRC_INC
-                                       | DWC_CTLL_FC(dws->fc)
                                        | DWC_CTLL_INT_EN);
+
+                       desc->lli.ctllo |= sconfig->device_fc ?
+                               DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
+                               DWC_CTLL_FC(DW_DMA_FC_D_M2P);
+
                        break;
                case DMA_DEV_TO_MEM:
                        desc->lli.dar = buf_addr + (period_len * i);
-                       desc->lli.sar = dws->rx_reg;
-                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
+                       desc->lli.sar = sconfig->src_addr;
+                       desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan)
                                        | DWC_CTLL_SRC_WIDTH(reg_width)
                                        | DWC_CTLL_DST_WIDTH(reg_width)
                                        | DWC_CTLL_DST_INC
                                        | DWC_CTLL_SRC_FIX
-                                       | DWC_CTLL_FC(dws->fc)
                                        | DWC_CTLL_INT_EN);
+
+                       desc->lli.ctllo |= sconfig->device_fc ?
+                               DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
+                               DWC_CTLL_FC(DW_DMA_FC_D_P2M);
+
                        break;
                default:
                        break;
@@ -1322,7 +1350,6 @@ void dw_dma_cyclic_free(struct dma_chan *chan)
        while (dma_readl(dw, CH_EN) & dwc->mask)
                cpu_relax();
 
-       dma_writel(dw, CLEAR.BLOCK, dwc->mask);
        dma_writel(dw, CLEAR.ERROR, dwc->mask);
        dma_writel(dw, CLEAR.XFER, dwc->mask);
 
@@ -1347,7 +1374,6 @@ static void dw_dma_off(struct dw_dma *dw)
        dma_writel(dw, CFG, 0);
 
        channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
-       channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
@@ -1369,7 +1395,7 @@ static int __init dw_probe(struct platform_device *pdev)
        int                     err;
        int                     i;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS)
                return -EINVAL;
 
@@ -1423,7 +1449,7 @@ static int __init dw_probe(struct platform_device *pdev)
                struct dw_dma_chan      *dwc = &dw->chan[i];
 
                dwc->chan.device = &dw->dma;
-               dwc->chan.cookie = dwc->completed = 1;
+               dma_cookie_init(&dwc->chan);
                if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
                        list_add_tail(&dwc->chan.device_node,
                                        &dw->dma.channels);
@@ -1432,7 +1458,7 @@ static int __init dw_probe(struct platform_device *pdev)
 
                /* 7 is highest priority & 0 is lowest. */
                if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
-                       dwc->priority = 7 - i;
+                       dwc->priority = pdata->nr_channels - i - 1;
                else
                        dwc->priority = i;
 
@@ -1449,13 +1475,11 @@ static int __init dw_probe(struct platform_device *pdev)
 
        /* Clear/disable all interrupts on all channels. */
        dma_writel(dw, CLEAR.XFER, dw->all_chan_mask);
-       dma_writel(dw, CLEAR.BLOCK, dw->all_chan_mask);
        dma_writel(dw, CLEAR.SRC_TRAN, dw->all_chan_mask);
        dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask);
        dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask);
 
        channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
-       channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
        channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
@@ -1562,6 +1586,10 @@ static int dw_resume_noirq(struct device *dev)
 static const struct dev_pm_ops dw_dev_pm_ops = {
        .suspend_noirq = dw_suspend_noirq,
        .resume_noirq = dw_resume_noirq,
+       .freeze_noirq = dw_suspend_noirq,
+       .thaw_noirq = dw_resume_noirq,
+       .restore_noirq = dw_resume_noirq,
+       .poweroff_noirq = dw_suspend_noirq,
 };
 
 static struct platform_driver dw_driver = {
index 5eef6946a36713bd7413ecd29c1751291c4cc41c..f298f69ecbf997959235f5f620087917b23a023c 100644 (file)
 
 #define DW_DMA_MAX_NR_CHANNELS 8
 
+/* flow controller */
+enum dw_dma_fc {
+       DW_DMA_FC_D_M2M,
+       DW_DMA_FC_D_M2P,
+       DW_DMA_FC_D_P2M,
+       DW_DMA_FC_D_P2P,
+       DW_DMA_FC_P_P2M,
+       DW_DMA_FC_SP_P2P,
+       DW_DMA_FC_P_M2P,
+       DW_DMA_FC_DP_P2P,
+};
+
 /*
  * Redefine this macro to handle differences between 32- and 64-bit
  * addressing, big vs. little endian, etc.
@@ -146,13 +158,15 @@ struct dw_dma_chan {
 
        /* these other elements are all protected by lock */
        unsigned long           flags;
-       dma_cookie_t            completed;
        struct list_head        active_list;
        struct list_head        queue;
        struct list_head        free_list;
        struct dw_cyclic_desc   *cdesc;
 
        unsigned int            descs_allocated;
+
+       /* configuration passed via DMA_SLAVE_CONFIG */
+       struct dma_slave_config dma_sconfig;
 };
 
 static inline struct dw_dma_chan_regs __iomem *
index 59e7a965772bfdff900aa1d82063d6f2510dd8c4..e6f133b78dc2c89f1144f3b6fd8b4ee100138e5e 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <mach/dma.h>
 
+#include "dmaengine.h"
+
 /* M2P registers */
 #define M2P_CONTROL                    0x0000
 #define M2P_CONTROL_STALLINT           BIT(0)
@@ -122,7 +124,6 @@ struct ep93xx_dma_desc {
  * @lock: lock protecting the fields following
  * @flags: flags for the channel
  * @buffer: which buffer to use next (0/1)
- * @last_completed: last completed cookie value
  * @active: flattened chain of descriptors currently being processed
  * @queue: pending descriptors which are handled next
  * @free_list: list of free descriptors which can be used
@@ -157,7 +158,6 @@ struct ep93xx_dma_chan {
 #define EP93XX_DMA_IS_CYCLIC           0
 
        int                             buffer;
-       dma_cookie_t                    last_completed;
        struct list_head                active;
        struct list_head                queue;
        struct list_head                free_list;
@@ -703,7 +703,7 @@ static void ep93xx_dma_tasklet(unsigned long data)
        desc = ep93xx_dma_get_active(edmac);
        if (desc) {
                if (desc->complete) {
-                       edmac->last_completed = desc->txd.cookie;
+                       dma_cookie_complete(&desc->txd);
                        list_splice_init(&edmac->active, &list);
                }
                callback = desc->txd.callback;
@@ -783,17 +783,10 @@ static dma_cookie_t ep93xx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        unsigned long flags;
 
        spin_lock_irqsave(&edmac->lock, flags);
-
-       cookie = edmac->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
+       cookie = dma_cookie_assign(tx);
 
        desc = container_of(tx, struct ep93xx_dma_desc, txd);
 
-       edmac->chan.cookie = cookie;
-       desc->txd.cookie = cookie;
-
        /*
         * If nothing is currently prosessed, we push this descriptor
         * directly to the hardware. Otherwise we put the descriptor
@@ -861,8 +854,7 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
                goto fail_clk_disable;
 
        spin_lock_irq(&edmac->lock);
-       edmac->last_completed = 1;
-       edmac->chan.cookie = 1;
+       dma_cookie_init(&edmac->chan);
        ret = edmac->edma->hw_setup(edmac);
        spin_unlock_irq(&edmac->lock);
 
@@ -983,13 +975,14 @@ fail:
  * @sg_len: number of entries in @sgl
  * @dir: direction of tha DMA transfer
  * @flags: flags for the descriptor
+ * @context: operation context (ignored)
  *
  * Returns a valid DMA descriptor or %NULL in case of failure.
  */
 static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                         unsigned int sg_len, enum dma_transfer_direction dir,
-                        unsigned long flags)
+                        unsigned long flags, void *context)
 {
        struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
        struct ep93xx_dma_desc *desc, *first;
@@ -1056,6 +1049,7 @@ fail:
  * @buf_len: length of the buffer (in bytes)
  * @period_len: lenght of a single period
  * @dir: direction of the operation
+ * @context: operation context (ignored)
  *
  * Prepares a descriptor for cyclic DMA operation. This means that once the
  * descriptor is submitted, we will be submitting in a @period_len sized
@@ -1068,7 +1062,7 @@ fail:
 static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
                           size_t buf_len, size_t period_len,
-                          enum dma_transfer_direction dir)
+                          enum dma_transfer_direction dir, void *context)
 {
        struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
        struct ep93xx_dma_desc *desc, *first;
@@ -1248,18 +1242,13 @@ static enum dma_status ep93xx_dma_tx_status(struct dma_chan *chan,
                                            struct dma_tx_state *state)
 {
        struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
-       dma_cookie_t last_used, last_completed;
        enum dma_status ret;
        unsigned long flags;
 
        spin_lock_irqsave(&edmac->lock, flags);
-       last_used = chan->cookie;
-       last_completed = edmac->last_completed;
+       ret = dma_cookie_status(chan, cookie, state);
        spin_unlock_irqrestore(&edmac->lock, flags);
 
-       ret = dma_async_is_complete(cookie, last_completed, last_used);
-       dma_set_tx_state(state, last_completed, last_used, 0);
-
        return ret;
 }
 
index b98070c33ca9d3b8aa42d1fb5085da9772957733..8f84761f98ba0d584b9b7a979e7fdd3c1beb8464 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/dmapool.h>
 #include <linux/of_platform.h>
 
+#include "dmaengine.h"
 #include "fsldma.h"
 
 #define chan_dbg(chan, fmt, arg...)                                    \
@@ -413,17 +414,10 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
         * assign cookies to all of the software descriptors
         * that make up this transaction
         */
-       cookie = chan->common.cookie;
        list_for_each_entry(child, &desc->tx_list, node) {
-               cookie++;
-               if (cookie < DMA_MIN_COOKIE)
-                       cookie = DMA_MIN_COOKIE;
-
-               child->async_tx.cookie = cookie;
+               cookie = dma_cookie_assign(&child->async_tx);
        }
 
-       chan->common.cookie = cookie;
-
        /* put this transaction onto the tail of the pending queue */
        append_ld_queue(chan, desc);
 
@@ -765,6 +759,7 @@ fail:
  * @sg_len: number of entries in @scatterlist
  * @direction: DMA direction
  * @flags: DMAEngine flags
+ * @context: transaction context (ignored)
  *
  * Prepare a set of descriptors for a DMA_SLAVE transaction. Following the
  * DMA_SLAVE API, this gets the device-specific information from the
@@ -772,7 +767,8 @@ fail:
  */
 static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
        struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
-       enum dma_transfer_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags,
+       void *context)
 {
        /*
         * This operation is not supported on the Freescale DMA controller
@@ -984,19 +980,14 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
                                        struct dma_tx_state *txstate)
 {
        struct fsldma_chan *chan = to_fsl_chan(dchan);
-       dma_cookie_t last_complete;
-       dma_cookie_t last_used;
+       enum dma_status ret;
        unsigned long flags;
 
        spin_lock_irqsave(&chan->desc_lock, flags);
-
-       last_complete = chan->completed_cookie;
-       last_used = dchan->cookie;
-
+       ret = dma_cookie_status(dchan, cookie, txstate);
        spin_unlock_irqrestore(&chan->desc_lock, flags);
 
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-       return dma_async_is_complete(cookie, last_complete, last_used);
+       return ret;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -1087,8 +1078,8 @@ static void dma_do_tasklet(unsigned long data)
 
                desc = to_fsl_desc(chan->ld_running.prev);
                cookie = desc->async_tx.cookie;
+               dma_cookie_complete(&desc->async_tx);
 
-               chan->completed_cookie = cookie;
                chan_dbg(chan, "completed_cookie=%d\n", cookie);
        }
 
@@ -1303,6 +1294,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
        chan->idle = true;
 
        chan->common.device = &fdev->common;
+       dma_cookie_init(&chan->common);
 
        /* find the IRQ line, if it exists in the device tree */
        chan->irq = irq_of_parse_and_map(node, 0);
index 9cb5aa57c677ea982339a87bc21df0a8e4d679e0..f5c38791fc7466f5d683b2ee49e718d8c29d5ca6 100644 (file)
@@ -137,7 +137,6 @@ struct fsldma_device {
 struct fsldma_chan {
        char name[8];                   /* Channel name */
        struct fsldma_chan_regs __iomem *regs;
-       dma_cookie_t completed_cookie;  /* The maximum cookie completed */
        spinlock_t desc_lock;           /* Descriptor operation lock */
        struct list_head ld_pending;    /* Link descriptors queue */
        struct list_head ld_running;    /* Link descriptors queue */
index 38586ba8da91fd4c63478670cff28ddf3ce14247..a45b5d2a59879a02b3566dfaf2c8304f8d693921 100644 (file)
@@ -5,6 +5,7 @@
  * found on i.MX1/21/27
  *
  * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright 2012 Javier Martin, Vista Silicon <javier.martin@vista-silicon.com>
  *
  * The code contained herein is licensed under the GNU General Public
  * License. You may obtain a copy of the GNU General Public License
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/dmaengine.h>
 #include <linux/module.h>
 
 #include <asm/irq.h>
-#include <mach/dma-v1.h>
+#include <mach/dma.h>
 #include <mach/hardware.h>
 
+#include "dmaengine.h"
+#define IMXDMA_MAX_CHAN_DESCRIPTORS    16
+#define IMX_DMA_CHANNELS  16
+
+#define IMX_DMA_2D_SLOTS       2
+#define IMX_DMA_2D_SLOT_A      0
+#define IMX_DMA_2D_SLOT_B      1
+
+#define IMX_DMA_LENGTH_LOOP    ((unsigned int)-1)
+#define IMX_DMA_MEMSIZE_32     (0 << 4)
+#define IMX_DMA_MEMSIZE_8      (1 << 4)
+#define IMX_DMA_MEMSIZE_16     (2 << 4)
+#define IMX_DMA_TYPE_LINEAR    (0 << 10)
+#define IMX_DMA_TYPE_2D                (1 << 10)
+#define IMX_DMA_TYPE_FIFO      (2 << 10)
+
+#define IMX_DMA_ERR_BURST     (1 << 0)
+#define IMX_DMA_ERR_REQUEST   (1 << 1)
+#define IMX_DMA_ERR_TRANSFER  (1 << 2)
+#define IMX_DMA_ERR_BUFFER    (1 << 3)
+#define IMX_DMA_ERR_TIMEOUT   (1 << 4)
+
+#define DMA_DCR     0x00               /* Control Register */
+#define DMA_DISR    0x04               /* Interrupt status Register */
+#define DMA_DIMR    0x08               /* Interrupt mask Register */
+#define DMA_DBTOSR  0x0c               /* Burst timeout status Register */
+#define DMA_DRTOSR  0x10               /* Request timeout Register */
+#define DMA_DSESR   0x14               /* Transfer Error Status Register */
+#define DMA_DBOSR   0x18               /* Buffer overflow status Register */
+#define DMA_DBTOCR  0x1c               /* Burst timeout control Register */
+#define DMA_WSRA    0x40               /* W-Size Register A */
+#define DMA_XSRA    0x44               /* X-Size Register A */
+#define DMA_YSRA    0x48               /* Y-Size Register A */
+#define DMA_WSRB    0x4c               /* W-Size Register B */
+#define DMA_XSRB    0x50               /* X-Size Register B */
+#define DMA_YSRB    0x54               /* Y-Size Register B */
+#define DMA_SAR(x)  (0x80 + ((x) << 6))        /* Source Address Registers */
+#define DMA_DAR(x)  (0x84 + ((x) << 6))        /* Destination Address Registers */
+#define DMA_CNTR(x) (0x88 + ((x) << 6))        /* Count Registers */
+#define DMA_CCR(x)  (0x8c + ((x) << 6))        /* Control Registers */
+#define DMA_RSSR(x) (0x90 + ((x) << 6))        /* Request source select Registers */
+#define DMA_BLR(x)  (0x94 + ((x) << 6))        /* Burst length Registers */
+#define DMA_RTOR(x) (0x98 + ((x) << 6))        /* Request timeout Registers */
+#define DMA_BUCR(x) (0x98 + ((x) << 6))        /* Bus Utilization Registers */
+#define DMA_CCNR(x) (0x9C + ((x) << 6))        /* Channel counter Registers */
+
+#define DCR_DRST           (1<<1)
+#define DCR_DEN            (1<<0)
+#define DBTOCR_EN          (1<<15)
+#define DBTOCR_CNT(x)      ((x) & 0x7fff)
+#define CNTR_CNT(x)        ((x) & 0xffffff)
+#define CCR_ACRPT          (1<<14)
+#define CCR_DMOD_LINEAR    (0x0 << 12)
+#define CCR_DMOD_2D        (0x1 << 12)
+#define CCR_DMOD_FIFO      (0x2 << 12)
+#define CCR_DMOD_EOBFIFO   (0x3 << 12)
+#define CCR_SMOD_LINEAR    (0x0 << 10)
+#define CCR_SMOD_2D        (0x1 << 10)
+#define CCR_SMOD_FIFO      (0x2 << 10)
+#define CCR_SMOD_EOBFIFO   (0x3 << 10)
+#define CCR_MDIR_DEC       (1<<9)
+#define CCR_MSEL_B         (1<<8)
+#define CCR_DSIZ_32        (0x0 << 6)
+#define CCR_DSIZ_8         (0x1 << 6)
+#define CCR_DSIZ_16        (0x2 << 6)
+#define CCR_SSIZ_32        (0x0 << 4)
+#define CCR_SSIZ_8         (0x1 << 4)
+#define CCR_SSIZ_16        (0x2 << 4)
+#define CCR_REN            (1<<3)
+#define CCR_RPT            (1<<2)
+#define CCR_FRC            (1<<1)
+#define CCR_CEN            (1<<0)
+#define RTOR_EN            (1<<15)
+#define RTOR_CLK           (1<<14)
+#define RTOR_PSC           (1<<13)
+
+enum  imxdma_prep_type {
+       IMXDMA_DESC_MEMCPY,
+       IMXDMA_DESC_INTERLEAVED,
+       IMXDMA_DESC_SLAVE_SG,
+       IMXDMA_DESC_CYCLIC,
+};
+
+struct imx_dma_2d_config {
+       u16             xsr;
+       u16             ysr;
+       u16             wsr;
+       int             count;
+};
+
+struct imxdma_desc {
+       struct list_head                node;
+       struct dma_async_tx_descriptor  desc;
+       enum dma_status                 status;
+       dma_addr_t                      src;
+       dma_addr_t                      dest;
+       size_t                          len;
+       enum dma_transfer_direction     direction;
+       enum imxdma_prep_type           type;
+       /* For memcpy and interleaved */
+       unsigned int                    config_port;
+       unsigned int                    config_mem;
+       /* For interleaved transfers */
+       unsigned int                    x;
+       unsigned int                    y;
+       unsigned int                    w;
+       /* For slave sg and cyclic */
+       struct scatterlist              *sg;
+       unsigned int                    sgcount;
+};
+
 struct imxdma_channel {
+       int                             hw_chaining;
+       struct timer_list               watchdog;
        struct imxdma_engine            *imxdma;
        unsigned int                    channel;
-       unsigned int                    imxdma_channel;
 
+       struct tasklet_struct           dma_tasklet;
+       struct list_head                ld_free;
+       struct list_head                ld_queue;
+       struct list_head                ld_active;
+       int                             descs_allocated;
        enum dma_slave_buswidth         word_size;
        dma_addr_t                      per_address;
        u32                             watermark_level;
        struct dma_chan                 chan;
-       spinlock_t                      lock;
        struct dma_async_tx_descriptor  desc;
-       dma_cookie_t                    last_completed;
        enum dma_status                 status;
        int                             dma_request;
        struct scatterlist              *sg_list;
+       u32                             ccr_from_device;
+       u32                             ccr_to_device;
+       bool                            enabled_2d;
+       int                             slot_2d;
 };
 
-#define MAX_DMA_CHANNELS 8
-
 struct imxdma_engine {
        struct device                   *dev;
        struct device_dma_parameters    dma_parms;
        struct dma_device               dma_device;
-       struct imxdma_channel           channel[MAX_DMA_CHANNELS];
+       void __iomem                    *base;
+       struct clk                      *dma_clk;
+       spinlock_t                      lock;
+       struct imx_dma_2d_config        slots_2d[IMX_DMA_2D_SLOTS];
+       struct imxdma_channel           channel[IMX_DMA_CHANNELS];
 };
 
 static struct imxdma_channel *to_imxdma_chan(struct dma_chan *chan)
@@ -60,36 +183,418 @@ static struct imxdma_channel *to_imxdma_chan(struct dma_chan *chan)
        return container_of(chan, struct imxdma_channel, chan);
 }
 
-static void imxdma_handle(struct imxdma_channel *imxdmac)
+static inline bool imxdma_chan_is_doing_cyclic(struct imxdma_channel *imxdmac)
+{
+       struct imxdma_desc *desc;
+
+       if (!list_empty(&imxdmac->ld_active)) {
+               desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc,
+                                       node);
+               if (desc->type == IMXDMA_DESC_CYCLIC)
+                       return true;
+       }
+       return false;
+}
+
+
+
+static void imx_dmav1_writel(struct imxdma_engine *imxdma, unsigned val,
+                            unsigned offset)
+{
+       __raw_writel(val, imxdma->base + offset);
+}
+
+static unsigned imx_dmav1_readl(struct imxdma_engine *imxdma, unsigned offset)
+{
+       return __raw_readl(imxdma->base + offset);
+}
+
+static int imxdma_hw_chain(struct imxdma_channel *imxdmac)
+{
+       if (cpu_is_mx27())
+               return imxdmac->hw_chaining;
+       else
+               return 0;
+}
+
+/*
+ * imxdma_sg_next - prepare next chunk for scatter-gather DMA emulation
+ */
+static inline int imxdma_sg_next(struct imxdma_desc *d)
 {
-       if (imxdmac->desc.callback)
-               imxdmac->desc.callback(imxdmac->desc.callback_param);
-       imxdmac->last_completed = imxdmac->desc.cookie;
+       struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       struct scatterlist *sg = d->sg;
+       unsigned long now;
+
+       now = min(d->len, sg->length);
+       if (d->len != IMX_DMA_LENGTH_LOOP)
+               d->len -= now;
+
+       if (d->direction == DMA_DEV_TO_MEM)
+               imx_dmav1_writel(imxdma, sg->dma_address,
+                                DMA_DAR(imxdmac->channel));
+       else
+               imx_dmav1_writel(imxdma, sg->dma_address,
+                                DMA_SAR(imxdmac->channel));
+
+       imx_dmav1_writel(imxdma, now, DMA_CNTR(imxdmac->channel));
+
+       dev_dbg(imxdma->dev, " %s channel: %d dst 0x%08x, src 0x%08x, "
+               "size 0x%08x\n", __func__, imxdmac->channel,
+                imx_dmav1_readl(imxdma, DMA_DAR(imxdmac->channel)),
+                imx_dmav1_readl(imxdma, DMA_SAR(imxdmac->channel)),
+                imx_dmav1_readl(imxdma, DMA_CNTR(imxdmac->channel)));
+
+       return now;
 }
 
-static void imxdma_irq_handler(int channel, void *data)
+static void imxdma_enable_hw(struct imxdma_desc *d)
 {
-       struct imxdma_channel *imxdmac = data;
+       struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       int channel = imxdmac->channel;
+       unsigned long flags;
+
+       dev_dbg(imxdma->dev, "%s channel %d\n", __func__, channel);
+
+       local_irq_save(flags);
+
+       imx_dmav1_writel(imxdma, 1 << channel, DMA_DISR);
+       imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_DIMR) &
+                        ~(1 << channel), DMA_DIMR);
+       imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) |
+                        CCR_CEN | CCR_ACRPT, DMA_CCR(channel));
+
+       if ((cpu_is_mx21() || cpu_is_mx27()) &&
+                       d->sg && imxdma_hw_chain(imxdmac)) {
+               d->sg = sg_next(d->sg);
+               if (d->sg) {
+                       u32 tmp;
+                       imxdma_sg_next(d);
+                       tmp = imx_dmav1_readl(imxdma, DMA_CCR(channel));
+                       imx_dmav1_writel(imxdma, tmp | CCR_RPT | CCR_ACRPT,
+                                        DMA_CCR(channel));
+               }
+       }
+
+       local_irq_restore(flags);
+}
+
+static void imxdma_disable_hw(struct imxdma_channel *imxdmac)
+{
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       int channel = imxdmac->channel;
+       unsigned long flags;
+
+       dev_dbg(imxdma->dev, "%s channel %d\n", __func__, channel);
+
+       if (imxdma_hw_chain(imxdmac))
+               del_timer(&imxdmac->watchdog);
+
+       local_irq_save(flags);
+       imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_DIMR) |
+                        (1 << channel), DMA_DIMR);
+       imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) &
+                        ~CCR_CEN, DMA_CCR(channel));
+       imx_dmav1_writel(imxdma, 1 << channel, DMA_DISR);
+       local_irq_restore(flags);
+}
+
+static void imxdma_watchdog(unsigned long data)
+{
+       struct imxdma_channel *imxdmac = (struct imxdma_channel *)data;
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       int channel = imxdmac->channel;
+
+       imx_dmav1_writel(imxdma, 0, DMA_CCR(channel));
 
-       imxdmac->status = DMA_SUCCESS;
-       imxdma_handle(imxdmac);
+       /* Tasklet watchdog error handler */
+       tasklet_schedule(&imxdmac->dma_tasklet);
+       dev_dbg(imxdma->dev, "channel %d: watchdog timeout!\n",
+               imxdmac->channel);
 }
 
-static void imxdma_err_handler(int channel, void *data, int error)
+static irqreturn_t imxdma_err_handler(int irq, void *dev_id)
 {
-       struct imxdma_channel *imxdmac = data;
+       struct imxdma_engine *imxdma = dev_id;
+       unsigned int err_mask;
+       int i, disr;
+       int errcode;
+
+       disr = imx_dmav1_readl(imxdma, DMA_DISR);
+
+       err_mask = imx_dmav1_readl(imxdma, DMA_DBTOSR) |
+                  imx_dmav1_readl(imxdma, DMA_DRTOSR) |
+                  imx_dmav1_readl(imxdma, DMA_DSESR)  |
+                  imx_dmav1_readl(imxdma, DMA_DBOSR);
+
+       if (!err_mask)
+               return IRQ_HANDLED;
+
+       imx_dmav1_writel(imxdma, disr & err_mask, DMA_DISR);
+
+       for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+               if (!(err_mask & (1 << i)))
+                       continue;
+               errcode = 0;
+
+               if (imx_dmav1_readl(imxdma, DMA_DBTOSR) & (1 << i)) {
+                       imx_dmav1_writel(imxdma, 1 << i, DMA_DBTOSR);
+                       errcode |= IMX_DMA_ERR_BURST;
+               }
+               if (imx_dmav1_readl(imxdma, DMA_DRTOSR) & (1 << i)) {
+                       imx_dmav1_writel(imxdma, 1 << i, DMA_DRTOSR);
+                       errcode |= IMX_DMA_ERR_REQUEST;
+               }
+               if (imx_dmav1_readl(imxdma, DMA_DSESR) & (1 << i)) {
+                       imx_dmav1_writel(imxdma, 1 << i, DMA_DSESR);
+                       errcode |= IMX_DMA_ERR_TRANSFER;
+               }
+               if (imx_dmav1_readl(imxdma, DMA_DBOSR) & (1 << i)) {
+                       imx_dmav1_writel(imxdma, 1 << i, DMA_DBOSR);
+                       errcode |= IMX_DMA_ERR_BUFFER;
+               }
+               /* Tasklet error handler */
+               tasklet_schedule(&imxdma->channel[i].dma_tasklet);
+
+               printk(KERN_WARNING
+                      "DMA timeout on channel %d -%s%s%s%s\n", i,
+                      errcode & IMX_DMA_ERR_BURST ?    " burst" : "",
+                      errcode & IMX_DMA_ERR_REQUEST ?  " request" : "",
+                      errcode & IMX_DMA_ERR_TRANSFER ? " transfer" : "",
+                      errcode & IMX_DMA_ERR_BUFFER ?   " buffer" : "");
+       }
+       return IRQ_HANDLED;
+}
+
+static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
+{
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       int chno = imxdmac->channel;
+       struct imxdma_desc *desc;
+
+       spin_lock(&imxdma->lock);
+       if (list_empty(&imxdmac->ld_active)) {
+               spin_unlock(&imxdma->lock);
+               goto out;
+       }
+
+       desc = list_first_entry(&imxdmac->ld_active,
+                               struct imxdma_desc,
+                               node);
+       spin_unlock(&imxdma->lock);
+
+       if (desc->sg) {
+               u32 tmp;
+               desc->sg = sg_next(desc->sg);
+
+               if (desc->sg) {
+                       imxdma_sg_next(desc);
+
+                       tmp = imx_dmav1_readl(imxdma, DMA_CCR(chno));
+
+                       if (imxdma_hw_chain(imxdmac)) {
+                               /* FIXME: The timeout should probably be
+                                * configurable
+                                */
+                               mod_timer(&imxdmac->watchdog,
+                                       jiffies + msecs_to_jiffies(500));
+
+                               tmp |= CCR_CEN | CCR_RPT | CCR_ACRPT;
+                               imx_dmav1_writel(imxdma, tmp, DMA_CCR(chno));
+                       } else {
+                               imx_dmav1_writel(imxdma, tmp & ~CCR_CEN,
+                                                DMA_CCR(chno));
+                               tmp |= CCR_CEN;
+                       }
+
+                       imx_dmav1_writel(imxdma, tmp, DMA_CCR(chno));
+
+                       if (imxdma_chan_is_doing_cyclic(imxdmac))
+                               /* Tasklet progression */
+                               tasklet_schedule(&imxdmac->dma_tasklet);
+
+                       return;
+               }
+
+               if (imxdma_hw_chain(imxdmac)) {
+                       del_timer(&imxdmac->watchdog);
+                       return;
+               }
+       }
+
+out:
+       imx_dmav1_writel(imxdma, 0, DMA_CCR(chno));
+       /* Tasklet irq */
+       tasklet_schedule(&imxdmac->dma_tasklet);
+}
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+{
+       struct imxdma_engine *imxdma = dev_id;
+       int i, disr;
+
+       if (cpu_is_mx21() || cpu_is_mx27())
+               imxdma_err_handler(irq, dev_id);
+
+       disr = imx_dmav1_readl(imxdma, DMA_DISR);
+
+       dev_dbg(imxdma->dev, "%s called, disr=0x%08x\n", __func__, disr);
+
+       imx_dmav1_writel(imxdma, disr, DMA_DISR);
+       for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+               if (disr & (1 << i))
+                       dma_irq_handle_channel(&imxdma->channel[i]);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int imxdma_xfer_desc(struct imxdma_desc *d)
+{
+       struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       unsigned long flags;
+       int slot = -1;
+       int i;
+
+       /* Configure and enable */
+       switch (d->type) {
+       case IMXDMA_DESC_INTERLEAVED:
+               /* Try to get a free 2D slot */
+               spin_lock_irqsave(&imxdma->lock, flags);
+               for (i = 0; i < IMX_DMA_2D_SLOTS; i++) {
+                       if ((imxdma->slots_2d[i].count > 0) &&
+                       ((imxdma->slots_2d[i].xsr != d->x) ||
+                       (imxdma->slots_2d[i].ysr != d->y) ||
+                       (imxdma->slots_2d[i].wsr != d->w)))
+                               continue;
+                       slot = i;
+                       break;
+               }
+               if (slot < 0)
+                       return -EBUSY;
+
+               imxdma->slots_2d[slot].xsr = d->x;
+               imxdma->slots_2d[slot].ysr = d->y;
+               imxdma->slots_2d[slot].wsr = d->w;
+               imxdma->slots_2d[slot].count++;
+
+               imxdmac->slot_2d = slot;
+               imxdmac->enabled_2d = true;
+               spin_unlock_irqrestore(&imxdma->lock, flags);
+
+               if (slot == IMX_DMA_2D_SLOT_A) {
+                       d->config_mem &= ~CCR_MSEL_B;
+                       d->config_port &= ~CCR_MSEL_B;
+                       imx_dmav1_writel(imxdma, d->x, DMA_XSRA);
+                       imx_dmav1_writel(imxdma, d->y, DMA_YSRA);
+                       imx_dmav1_writel(imxdma, d->w, DMA_WSRA);
+               } else {
+                       d->config_mem |= CCR_MSEL_B;
+                       d->config_port |= CCR_MSEL_B;
+                       imx_dmav1_writel(imxdma, d->x, DMA_XSRB);
+                       imx_dmav1_writel(imxdma, d->y, DMA_YSRB);
+                       imx_dmav1_writel(imxdma, d->w, DMA_WSRB);
+               }
+               /*
+                * We fall-through here intentionally, since a 2D transfer is
+                * similar to MEMCPY just adding the 2D slot configuration.
+                */
+       case IMXDMA_DESC_MEMCPY:
+               imx_dmav1_writel(imxdma, d->src, DMA_SAR(imxdmac->channel));
+               imx_dmav1_writel(imxdma, d->dest, DMA_DAR(imxdmac->channel));
+               imx_dmav1_writel(imxdma, d->config_mem | (d->config_port << 2),
+                        DMA_CCR(imxdmac->channel));
+
+               imx_dmav1_writel(imxdma, d->len, DMA_CNTR(imxdmac->channel));
+
+               dev_dbg(imxdma->dev, "%s channel: %d dest=0x%08x src=0x%08x "
+                       "dma_length=%d\n", __func__, imxdmac->channel,
+                       d->dest, d->src, d->len);
+
+               break;
+       /* Cyclic transfer is the same as slave_sg with special sg configuration. */
+       case IMXDMA_DESC_CYCLIC:
+       case IMXDMA_DESC_SLAVE_SG:
+               if (d->direction == DMA_DEV_TO_MEM) {
+                       imx_dmav1_writel(imxdma, imxdmac->per_address,
+                                        DMA_SAR(imxdmac->channel));
+                       imx_dmav1_writel(imxdma, imxdmac->ccr_from_device,
+                                        DMA_CCR(imxdmac->channel));
+
+                       dev_dbg(imxdma->dev, "%s channel: %d sg=%p sgcount=%d "
+                               "total length=%d dev_addr=0x%08x (dev2mem)\n",
+                               __func__, imxdmac->channel, d->sg, d->sgcount,
+                               d->len, imxdmac->per_address);
+               } else if (d->direction == DMA_MEM_TO_DEV) {
+                       imx_dmav1_writel(imxdma, imxdmac->per_address,
+                                        DMA_DAR(imxdmac->channel));
+                       imx_dmav1_writel(imxdma, imxdmac->ccr_to_device,
+                                        DMA_CCR(imxdmac->channel));
+
+                       dev_dbg(imxdma->dev, "%s channel: %d sg=%p sgcount=%d "
+                               "total length=%d dev_addr=0x%08x (mem2dev)\n",
+                               __func__, imxdmac->channel, d->sg, d->sgcount,
+                               d->len, imxdmac->per_address);
+               } else {
+                       dev_err(imxdma->dev, "%s channel: %d bad dma mode\n",
+                               __func__, imxdmac->channel);
+                       return -EINVAL;
+               }
+
+               imxdma_sg_next(d);
 
-       imxdmac->status = DMA_ERROR;
-       imxdma_handle(imxdmac);
+               break;
+       default:
+               return -EINVAL;
+       }
+       imxdma_enable_hw(d);
+       return 0;
 }
 
-static void imxdma_progression(int channel, void *data,
-               struct scatterlist *sg)
+static void imxdma_tasklet(unsigned long data)
 {
-       struct imxdma_channel *imxdmac = data;
+       struct imxdma_channel *imxdmac = (void *)data;
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       struct imxdma_desc *desc;
 
-       imxdmac->status = DMA_SUCCESS;
-       imxdma_handle(imxdmac);
+       spin_lock(&imxdma->lock);
+
+       if (list_empty(&imxdmac->ld_active)) {
+               /* Someone might have called terminate all */
+               goto out;
+       }
+       desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node);
+
+       if (desc->desc.callback)
+               desc->desc.callback(desc->desc.callback_param);
+
+       dma_cookie_complete(&desc->desc);
+
+       /* If we are dealing with a cyclic descriptor keep it on ld_active */
+       if (imxdma_chan_is_doing_cyclic(imxdmac))
+               goto out;
+
+       /* Free 2D slot if it was an interleaved transfer */
+       if (imxdmac->enabled_2d) {
+               imxdma->slots_2d[imxdmac->slot_2d].count--;
+               imxdmac->enabled_2d = false;
+       }
+
+       list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
+
+       if (!list_empty(&imxdmac->ld_queue)) {
+               desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
+                                       node);
+               list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
+               if (imxdma_xfer_desc(desc) < 0)
+                       dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
+                                __func__, imxdmac->channel);
+       }
+out:
+       spin_unlock(&imxdma->lock);
 }
 
 static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
@@ -97,13 +602,18 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
        struct dma_slave_config *dmaengine_cfg = (void *)arg;
-       int ret;
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       unsigned long flags;
        unsigned int mode = 0;
 
        switch (cmd) {
        case DMA_TERMINATE_ALL:
-               imxdmac->status = DMA_ERROR;
-               imx_dma_disable(imxdmac->imxdma_channel);
+               imxdma_disable_hw(imxdmac);
+
+               spin_lock_irqsave(&imxdma->lock, flags);
+               list_splice_tail_init(&imxdmac->ld_active, &imxdmac->ld_free);
+               list_splice_tail_init(&imxdmac->ld_queue, &imxdmac->ld_free);
+               spin_unlock_irqrestore(&imxdma->lock, flags);
                return 0;
        case DMA_SLAVE_CONFIG:
                if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
@@ -128,16 +638,22 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                        mode = IMX_DMA_MEMSIZE_32;
                        break;
                }
-               ret = imx_dma_config_channel(imxdmac->imxdma_channel,
-                               mode | IMX_DMA_TYPE_FIFO,
-                               IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
-                               imxdmac->dma_request, 1);
-
-               if (ret)
-                       return ret;
 
-               imx_dma_config_burstlen(imxdmac->imxdma_channel,
-                               imxdmac->watermark_level * imxdmac->word_size);
+               imxdmac->hw_chaining = 1;
+               if (!imxdma_hw_chain(imxdmac))
+                       return -EINVAL;
+               imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) |
+                       ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) |
+                       CCR_REN;
+               imxdmac->ccr_to_device =
+                       (IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) |
+                       ((mode | IMX_DMA_TYPE_FIFO) << 2) | CCR_REN;
+               imx_dmav1_writel(imxdma, imxdmac->dma_request,
+                                DMA_RSSR(imxdmac->channel));
+
+               /* Set burst length */
+               imx_dmav1_writel(imxdma, imxdmac->watermark_level *
+                               imxdmac->word_size, DMA_BLR(imxdmac->channel));
 
                return 0;
        default:
@@ -151,43 +667,20 @@ static enum dma_status imxdma_tx_status(struct dma_chan *chan,
                                            dma_cookie_t cookie,
                                            struct dma_tx_state *txstate)
 {
-       struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
-       dma_cookie_t last_used;
-       enum dma_status ret;
-
-       last_used = chan->cookie;
-
-       ret = dma_async_is_complete(cookie, imxdmac->last_completed, last_used);
-       dma_set_tx_state(txstate, imxdmac->last_completed, last_used, 0);
-
-       return ret;
-}
-
-static dma_cookie_t imxdma_assign_cookie(struct imxdma_channel *imxdma)
-{
-       dma_cookie_t cookie = imxdma->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       imxdma->chan.cookie = cookie;
-       imxdma->desc.cookie = cookie;
-
-       return cookie;
+       return dma_cookie_status(chan, cookie, txstate);
 }
 
 static dma_cookie_t imxdma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(tx->chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
        dma_cookie_t cookie;
+       unsigned long flags;
 
-       spin_lock_irq(&imxdmac->lock);
-
-       cookie = imxdma_assign_cookie(imxdmac);
-
-       imx_dma_enable(imxdmac->imxdma_channel);
-
-       spin_unlock_irq(&imxdmac->lock);
+       spin_lock_irqsave(&imxdma->lock, flags);
+       list_move_tail(imxdmac->ld_free.next, &imxdmac->ld_queue);
+       cookie = dma_cookie_assign(tx);
+       spin_unlock_irqrestore(&imxdma->lock, flags);
 
        return cookie;
 }
@@ -197,23 +690,52 @@ static int imxdma_alloc_chan_resources(struct dma_chan *chan)
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
        struct imx_dma_data *data = chan->private;
 
-       imxdmac->dma_request = data->dma_request;
+       if (data != NULL)
+               imxdmac->dma_request = data->dma_request;
 
-       dma_async_tx_descriptor_init(&imxdmac->desc, chan);
-       imxdmac->desc.tx_submit = imxdma_tx_submit;
-       /* txd.flags will be overwritten in prep funcs */
-       imxdmac->desc.flags = DMA_CTRL_ACK;
+       while (imxdmac->descs_allocated < IMXDMA_MAX_CHAN_DESCRIPTORS) {
+               struct imxdma_desc *desc;
 
-       imxdmac->status = DMA_SUCCESS;
+               desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+               if (!desc)
+                       break;
+               __memzero(&desc->desc, sizeof(struct dma_async_tx_descriptor));
+               dma_async_tx_descriptor_init(&desc->desc, chan);
+               desc->desc.tx_submit = imxdma_tx_submit;
+               /* txd.flags will be overwritten in prep funcs */
+               desc->desc.flags = DMA_CTRL_ACK;
+               desc->status = DMA_SUCCESS;
+
+               list_add_tail(&desc->node, &imxdmac->ld_free);
+               imxdmac->descs_allocated++;
+       }
 
-       return 0;
+       if (!imxdmac->descs_allocated)
+               return -ENOMEM;
+
+       return imxdmac->descs_allocated;
 }
 
 static void imxdma_free_chan_resources(struct dma_chan *chan)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       struct imxdma_desc *desc, *_desc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&imxdma->lock, flags);
+
+       imxdma_disable_hw(imxdmac);
+       list_splice_tail_init(&imxdmac->ld_active, &imxdmac->ld_free);
+       list_splice_tail_init(&imxdmac->ld_queue, &imxdmac->ld_free);
 
-       imx_dma_disable(imxdmac->imxdma_channel);
+       spin_unlock_irqrestore(&imxdma->lock, flags);
+
+       list_for_each_entry_safe(desc, _desc, &imxdmac->ld_free, node) {
+               kfree(desc);
+               imxdmac->descs_allocated--;
+       }
+       INIT_LIST_HEAD(&imxdmac->ld_free);
 
        if (imxdmac->sg_list) {
                kfree(imxdmac->sg_list);
@@ -224,27 +746,23 @@ static void imxdma_free_chan_resources(struct dma_chan *chan)
 static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags)
+               unsigned long flags, void *context)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
        struct scatterlist *sg;
-       int i, ret, dma_length = 0;
-       unsigned int dmamode;
+       int i, dma_length = 0;
+       struct imxdma_desc *desc;
 
-       if (imxdmac->status == DMA_IN_PROGRESS)
+       if (list_empty(&imxdmac->ld_free) ||
+           imxdma_chan_is_doing_cyclic(imxdmac))
                return NULL;
 
-       imxdmac->status = DMA_IN_PROGRESS;
+       desc = list_first_entry(&imxdmac->ld_free, struct imxdma_desc, node);
 
        for_each_sg(sgl, sg, sg_len, i) {
                dma_length += sg->length;
        }
 
-       if (direction == DMA_DEV_TO_MEM)
-               dmamode = DMA_MODE_READ;
-       else
-               dmamode = DMA_MODE_WRITE;
-
        switch (imxdmac->word_size) {
        case DMA_SLAVE_BUSWIDTH_4_BYTES:
                if (sgl->length & 3 || sgl->dma_address & 3)
@@ -260,37 +778,41 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
                return NULL;
        }
 
-       ret = imx_dma_setup_sg(imxdmac->imxdma_channel, sgl, sg_len,
-                dma_length, imxdmac->per_address, dmamode);
-       if (ret)
-               return NULL;
+       desc->type = IMXDMA_DESC_SLAVE_SG;
+       desc->sg = sgl;
+       desc->sgcount = sg_len;
+       desc->len = dma_length;
+       desc->direction = direction;
+       if (direction == DMA_DEV_TO_MEM) {
+               desc->src = imxdmac->per_address;
+       } else {
+               desc->dest = imxdmac->per_address;
+       }
+       desc->desc.callback = NULL;
+       desc->desc.callback_param = NULL;
 
-       return &imxdmac->desc;
+       return &desc->desc;
 }
 
 static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
-               size_t period_len, enum dma_transfer_direction direction)
+               size_t period_len, enum dma_transfer_direction direction,
+               void *context)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
        struct imxdma_engine *imxdma = imxdmac->imxdma;
-       int i, ret;
+       struct imxdma_desc *desc;
+       int i;
        unsigned int periods = buf_len / period_len;
-       unsigned int dmamode;
 
        dev_dbg(imxdma->dev, "%s channel: %d buf_len=%d period_len=%d\n",
                        __func__, imxdmac->channel, buf_len, period_len);
 
-       if (imxdmac->status == DMA_IN_PROGRESS)
+       if (list_empty(&imxdmac->ld_free) ||
+           imxdma_chan_is_doing_cyclic(imxdmac))
                return NULL;
-       imxdmac->status = DMA_IN_PROGRESS;
 
-       ret = imx_dma_setup_progression_handler(imxdmac->imxdma_channel,
-                       imxdma_progression);
-       if (ret) {
-               dev_err(imxdma->dev, "Failed to setup the DMA handler\n");
-               return NULL;
-       }
+       desc = list_first_entry(&imxdmac->ld_free, struct imxdma_desc, node);
 
        if (imxdmac->sg_list)
                kfree(imxdmac->sg_list);
@@ -316,62 +838,221 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
        imxdmac->sg_list[periods].page_link =
                ((unsigned long)imxdmac->sg_list | 0x01) & ~0x02;
 
-       if (direction == DMA_DEV_TO_MEM)
-               dmamode = DMA_MODE_READ;
-       else
-               dmamode = DMA_MODE_WRITE;
+       desc->type = IMXDMA_DESC_CYCLIC;
+       desc->sg = imxdmac->sg_list;
+       desc->sgcount = periods;
+       desc->len = IMX_DMA_LENGTH_LOOP;
+       desc->direction = direction;
+       if (direction == DMA_DEV_TO_MEM) {
+               desc->src = imxdmac->per_address;
+       } else {
+               desc->dest = imxdmac->per_address;
+       }
+       desc->desc.callback = NULL;
+       desc->desc.callback_param = NULL;
+
+       return &desc->desc;
+}
+
+static struct dma_async_tx_descriptor *imxdma_prep_dma_memcpy(
+       struct dma_chan *chan, dma_addr_t dest,
+       dma_addr_t src, size_t len, unsigned long flags)
+{
+       struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       struct imxdma_desc *desc;
 
-       ret = imx_dma_setup_sg(imxdmac->imxdma_channel, imxdmac->sg_list, periods,
-                IMX_DMA_LENGTH_LOOP, imxdmac->per_address, dmamode);
-       if (ret)
+       dev_dbg(imxdma->dev, "%s channel: %d src=0x%x dst=0x%x len=%d\n",
+                       __func__, imxdmac->channel, src, dest, len);
+
+       if (list_empty(&imxdmac->ld_free) ||
+           imxdma_chan_is_doing_cyclic(imxdmac))
                return NULL;
 
-       return &imxdmac->desc;
+       desc = list_first_entry(&imxdmac->ld_free, struct imxdma_desc, node);
+
+       desc->type = IMXDMA_DESC_MEMCPY;
+       desc->src = src;
+       desc->dest = dest;
+       desc->len = len;
+       desc->direction = DMA_MEM_TO_MEM;
+       desc->config_port = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR;
+       desc->config_mem = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR;
+       desc->desc.callback = NULL;
+       desc->desc.callback_param = NULL;
+
+       return &desc->desc;
+}
+
+static struct dma_async_tx_descriptor *imxdma_prep_dma_interleaved(
+       struct dma_chan *chan, struct dma_interleaved_template *xt,
+       unsigned long flags)
+{
+       struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       struct imxdma_desc *desc;
+
+       dev_dbg(imxdma->dev, "%s channel: %d src_start=0x%x dst_start=0x%x\n"
+               "   src_sgl=%s dst_sgl=%s numf=%d frame_size=%d\n", __func__,
+               imxdmac->channel, xt->src_start, xt->dst_start,
+               xt->src_sgl ? "true" : "false", xt->dst_sgl ? "true" : "false",
+               xt->numf, xt->frame_size);
+
+       if (list_empty(&imxdmac->ld_free) ||
+           imxdma_chan_is_doing_cyclic(imxdmac))
+               return NULL;
+
+       if (xt->frame_size != 1 || xt->numf <= 0 || xt->dir != DMA_MEM_TO_MEM)
+               return NULL;
+
+       desc = list_first_entry(&imxdmac->ld_free, struct imxdma_desc, node);
+
+       desc->type = IMXDMA_DESC_INTERLEAVED;
+       desc->src = xt->src_start;
+       desc->dest = xt->dst_start;
+       desc->x = xt->sgl[0].size;
+       desc->y = xt->numf;
+       desc->w = xt->sgl[0].icg + desc->x;
+       desc->len = desc->x * desc->y;
+       desc->direction = DMA_MEM_TO_MEM;
+       desc->config_port = IMX_DMA_MEMSIZE_32;
+       desc->config_mem = IMX_DMA_MEMSIZE_32;
+       if (xt->src_sgl)
+               desc->config_mem |= IMX_DMA_TYPE_2D;
+       if (xt->dst_sgl)
+               desc->config_port |= IMX_DMA_TYPE_2D;
+       desc->desc.callback = NULL;
+       desc->desc.callback_param = NULL;
+
+       return &desc->desc;
 }
 
 static void imxdma_issue_pending(struct dma_chan *chan)
 {
-       /*
-        * Nothing to do. We only have a single descriptor
-        */
+       struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
+       struct imxdma_engine *imxdma = imxdmac->imxdma;
+       struct imxdma_desc *desc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&imxdma->lock, flags);
+       if (list_empty(&imxdmac->ld_active) &&
+           !list_empty(&imxdmac->ld_queue)) {
+               desc = list_first_entry(&imxdmac->ld_queue,
+                                       struct imxdma_desc, node);
+
+               if (imxdma_xfer_desc(desc) < 0) {
+                       dev_warn(imxdma->dev,
+                                "%s: channel: %d couldn't issue DMA xfer\n",
+                                __func__, imxdmac->channel);
+               } else {
+                       list_move_tail(imxdmac->ld_queue.next,
+                                      &imxdmac->ld_active);
+               }
+       }
+       spin_unlock_irqrestore(&imxdma->lock, flags);
 }
 
 static int __init imxdma_probe(struct platform_device *pdev)
-{
+       {
        struct imxdma_engine *imxdma;
        int ret, i;
 
+
        imxdma = kzalloc(sizeof(*imxdma), GFP_KERNEL);
        if (!imxdma)
                return -ENOMEM;
 
+       if (cpu_is_mx1()) {
+               imxdma->base = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
+       } else if (cpu_is_mx21()) {
+               imxdma->base = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
+       } else if (cpu_is_mx27()) {
+               imxdma->base = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
+       } else {
+               kfree(imxdma);
+               return 0;
+       }
+
+       imxdma->dma_clk = clk_get(NULL, "dma");
+       if (IS_ERR(imxdma->dma_clk))
+               return PTR_ERR(imxdma->dma_clk);
+       clk_enable(imxdma->dma_clk);
+
+       /* reset DMA module */
+       imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR);
+
+       if (cpu_is_mx1()) {
+               ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma);
+               if (ret) {
+                       dev_warn(imxdma->dev, "Can't register IRQ for DMA\n");
+                       kfree(imxdma);
+                       return ret;
+               }
+
+               ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma);
+               if (ret) {
+                       dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");
+                       free_irq(MX1_DMA_INT, NULL);
+                       kfree(imxdma);
+                       return ret;
+               }
+       }
+
+       /* enable DMA module */
+       imx_dmav1_writel(imxdma, DCR_DEN, DMA_DCR);
+
+       /* clear all interrupts */
+       imx_dmav1_writel(imxdma, (1 << IMX_DMA_CHANNELS) - 1, DMA_DISR);
+
+       /* disable interrupts */
+       imx_dmav1_writel(imxdma, (1 << IMX_DMA_CHANNELS) - 1, DMA_DIMR);
+
        INIT_LIST_HEAD(&imxdma->dma_device.channels);
 
        dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask);
        dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask);
+       dma_cap_set(DMA_MEMCPY, imxdma->dma_device.cap_mask);
+       dma_cap_set(DMA_INTERLEAVE, imxdma->dma_device.cap_mask);
+
+       /* Initialize 2D global parameters */
+       for (i = 0; i < IMX_DMA_2D_SLOTS; i++)
+               imxdma->slots_2d[i].count = 0;
+
+       spin_lock_init(&imxdma->lock);
 
        /* Initialize channel parameters */
-       for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+       for (i = 0; i < IMX_DMA_CHANNELS; i++) {
                struct imxdma_channel *imxdmac = &imxdma->channel[i];
 
-               imxdmac->imxdma_channel = imx_dma_request_by_prio("dmaengine",
-                               DMA_PRIO_MEDIUM);
-               if ((int)imxdmac->channel < 0) {
-                       ret = -ENODEV;
-                       goto err_init;
+               if (cpu_is_mx21() || cpu_is_mx27()) {
+                       ret = request_irq(MX2x_INT_DMACH0 + i,
+                                       dma_irq_handler, 0, "DMA", imxdma);
+                       if (ret) {
+                               dev_warn(imxdma->dev, "Can't register IRQ %d "
+                                        "for DMA channel %d\n",
+                                        MX2x_INT_DMACH0 + i, i);
+                               goto err_init;
+                       }
+                       init_timer(&imxdmac->watchdog);
+                       imxdmac->watchdog.function = &imxdma_watchdog;
+                       imxdmac->watchdog.data = (unsigned long)imxdmac;
                }
 
-               imx_dma_setup_handlers(imxdmac->imxdma_channel,
-                      imxdma_irq_handler, imxdma_err_handler, imxdmac);
-
                imxdmac->imxdma = imxdma;
-               spin_lock_init(&imxdmac->lock);
 
+               INIT_LIST_HEAD(&imxdmac->ld_queue);
+               INIT_LIST_HEAD(&imxdmac->ld_free);
+               INIT_LIST_HEAD(&imxdmac->ld_active);
+
+               tasklet_init(&imxdmac->dma_tasklet, imxdma_tasklet,
+                            (unsigned long)imxdmac);
                imxdmac->chan.device = &imxdma->dma_device;
+               dma_cookie_init(&imxdmac->chan);
                imxdmac->channel = i;
 
                /* Add the channel to the DMAC list */
-               list_add_tail(&imxdmac->chan.device_node, &imxdma->dma_device.channels);
+               list_add_tail(&imxdmac->chan.device_node,
+                             &imxdma->dma_device.channels);
        }
 
        imxdma->dev = &pdev->dev;
@@ -382,11 +1063,14 @@ static int __init imxdma_probe(struct platform_device *pdev)
        imxdma->dma_device.device_tx_status = imxdma_tx_status;
        imxdma->dma_device.device_prep_slave_sg = imxdma_prep_slave_sg;
        imxdma->dma_device.device_prep_dma_cyclic = imxdma_prep_dma_cyclic;
+       imxdma->dma_device.device_prep_dma_memcpy = imxdma_prep_dma_memcpy;
+       imxdma->dma_device.device_prep_interleaved_dma = imxdma_prep_dma_interleaved;
        imxdma->dma_device.device_control = imxdma_control;
        imxdma->dma_device.device_issue_pending = imxdma_issue_pending;
 
        platform_set_drvdata(pdev, imxdma);
 
+       imxdma->dma_device.copy_align = 2; /* 2^2 = 4 bytes alignment */
        imxdma->dma_device.dev->dma_parms = &imxdma->dma_parms;
        dma_set_max_seg_size(imxdma->dma_device.dev, 0xffffff);
 
@@ -399,9 +1083,13 @@ static int __init imxdma_probe(struct platform_device *pdev)
        return 0;
 
 err_init:
-       while (--i >= 0) {
-               struct imxdma_channel *imxdmac = &imxdma->channel[i];
-               imx_dma_free(imxdmac->imxdma_channel);
+
+       if (cpu_is_mx21() || cpu_is_mx27()) {
+               while (--i >= 0)
+                       free_irq(MX2x_INT_DMACH0 + i, NULL);
+       } else if cpu_is_mx1() {
+               free_irq(MX1_DMA_INT, NULL);
+               free_irq(MX1_DMA_ERR, NULL);
        }
 
        kfree(imxdma);
@@ -415,10 +1103,12 @@ static int __exit imxdma_remove(struct platform_device *pdev)
 
         dma_async_device_unregister(&imxdma->dma_device);
 
-       for (i = 0; i < MAX_DMA_CHANNELS; i++) {
-               struct imxdma_channel *imxdmac = &imxdma->channel[i];
-
-                imx_dma_free(imxdmac->imxdma_channel);
+       if (cpu_is_mx21() || cpu_is_mx27()) {
+               for (i = 0; i < IMX_DMA_CHANNELS; i++)
+                       free_irq(MX2x_INT_DMACH0 + i, NULL);
+       } else if cpu_is_mx1() {
+               free_irq(MX1_DMA_INT, NULL);
+               free_irq(MX1_DMA_ERR, NULL);
        }
 
         kfree(imxdma);
index 63540d3e21534ae8cfe596c1d03a4ce850bcc200..d3e38e28bb6b19a480eb1b05b732a0dc2f40eb7f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/bitops.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
@@ -41,6 +42,8 @@
 #include <mach/dma.h>
 #include <mach/hardware.h>
 
+#include "dmaengine.h"
+
 /* SDMA registers */
 #define SDMA_H_C0PTR           0x000
 #define SDMA_H_INTR            0x004
@@ -259,19 +262,18 @@ struct sdma_channel {
        unsigned int                    pc_from_device, pc_to_device;
        unsigned long                   flags;
        dma_addr_t                      per_address;
-       u32                             event_mask0, event_mask1;
-       u32                             watermark_level;
+       unsigned long                   event_mask[2];
+       unsigned long                   watermark_level;
        u32                             shp_addr, per_addr;
        struct dma_chan                 chan;
        spinlock_t                      lock;
        struct dma_async_tx_descriptor  desc;
-       dma_cookie_t                    last_completed;
        enum dma_status                 status;
        unsigned int                    chn_count;
        unsigned int                    chn_real_count;
 };
 
-#define IMX_DMA_SG_LOOP                (1 << 0)
+#define IMX_DMA_SG_LOOP                BIT(0)
 
 #define MAX_DMA_CHANNELS 32
 #define MXC_SDMA_DEFAULT_PRIORITY 1
@@ -345,9 +347,9 @@ static const struct of_device_id sdma_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, sdma_dt_ids);
 
-#define SDMA_H_CONFIG_DSPDMA   (1 << 12) /* indicates if the DSPDMA is used */
-#define SDMA_H_CONFIG_RTD_PINS (1 << 11) /* indicates if Real-Time Debug pins are enabled */
-#define SDMA_H_CONFIG_ACR      (1 << 4)  /* indicates if AHB freq /core freq = 2 or 1 */
+#define SDMA_H_CONFIG_DSPDMA   BIT(12) /* indicates if the DSPDMA is used */
+#define SDMA_H_CONFIG_RTD_PINS BIT(11) /* indicates if Real-Time Debug pins are enabled */
+#define SDMA_H_CONFIG_ACR      BIT(4)  /* indicates if AHB freq /core freq = 2 or 1 */
 #define SDMA_H_CONFIG_CSM      (3)       /* indicates which context switch mode is selected*/
 
 static inline u32 chnenbl_ofs(struct sdma_engine *sdma, unsigned int event)
@@ -362,37 +364,42 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
 {
        struct sdma_engine *sdma = sdmac->sdma;
        int channel = sdmac->channel;
-       u32 evt, mcu, dsp;
+       unsigned long evt, mcu, dsp;
 
        if (event_override && mcu_override && dsp_override)
                return -EINVAL;
 
-       evt = __raw_readl(sdma->regs + SDMA_H_EVTOVR);
-       mcu = __raw_readl(sdma->regs + SDMA_H_HOSTOVR);
-       dsp = __raw_readl(sdma->regs + SDMA_H_DSPOVR);
+       evt = readl_relaxed(sdma->regs + SDMA_H_EVTOVR);
+       mcu = readl_relaxed(sdma->regs + SDMA_H_HOSTOVR);
+       dsp = readl_relaxed(sdma->regs + SDMA_H_DSPOVR);
 
        if (dsp_override)
-               dsp &= ~(1 << channel);
+               __clear_bit(channel, &dsp);
        else
-               dsp |= (1 << channel);
+               __set_bit(channel, &dsp);
 
        if (event_override)
-               evt &= ~(1 << channel);
+               __clear_bit(channel, &evt);
        else
-               evt |= (1 << channel);
+               __set_bit(channel, &evt);
 
        if (mcu_override)
-               mcu &= ~(1 << channel);
+               __clear_bit(channel, &mcu);
        else
-               mcu |= (1 << channel);
+               __set_bit(channel, &mcu);
 
-       __raw_writel(evt, sdma->regs + SDMA_H_EVTOVR);
-       __raw_writel(mcu, sdma->regs + SDMA_H_HOSTOVR);
-       __raw_writel(dsp, sdma->regs + SDMA_H_DSPOVR);
+       writel_relaxed(evt, sdma->regs + SDMA_H_EVTOVR);
+       writel_relaxed(mcu, sdma->regs + SDMA_H_HOSTOVR);
+       writel_relaxed(dsp, sdma->regs + SDMA_H_DSPOVR);
 
        return 0;
 }
 
+static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
+{
+       writel(BIT(channel), sdma->regs + SDMA_H_START);
+}
+
 /*
  * sdma_run_channel - run a channel and wait till it's done
  */
@@ -404,7 +411,7 @@ static int sdma_run_channel(struct sdma_channel *sdmac)
 
        init_completion(&sdmac->done);
 
-       __raw_writel(1 << channel, sdma->regs + SDMA_H_START);
+       sdma_enable_channel(sdma, channel);
 
        ret = wait_for_completion_timeout(&sdmac->done, HZ);
 
@@ -451,12 +458,12 @@ static void sdma_event_enable(struct sdma_channel *sdmac, unsigned int event)
 {
        struct sdma_engine *sdma = sdmac->sdma;
        int channel = sdmac->channel;
-       u32 val;
+       unsigned long val;
        u32 chnenbl = chnenbl_ofs(sdma, event);
 
-       val = __raw_readl(sdma->regs + chnenbl);
-       val |= (1 << channel);
-       __raw_writel(val, sdma->regs + chnenbl);
+       val = readl_relaxed(sdma->regs + chnenbl);
+       __set_bit(channel, &val);
+       writel_relaxed(val, sdma->regs + chnenbl);
 }
 
 static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
@@ -464,11 +471,11 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
        struct sdma_engine *sdma = sdmac->sdma;
        int channel = sdmac->channel;
        u32 chnenbl = chnenbl_ofs(sdma, event);
-       u32 val;
+       unsigned long val;
 
-       val = __raw_readl(sdma->regs + chnenbl);
-       val &= ~(1 << channel);
-       __raw_writel(val, sdma->regs + chnenbl);
+       val = readl_relaxed(sdma->regs + chnenbl);
+       __clear_bit(channel, &val);
+       writel_relaxed(val, sdma->regs + chnenbl);
 }
 
 static void sdma_handle_channel_loop(struct sdma_channel *sdmac)
@@ -522,7 +529,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
        else
                sdmac->status = DMA_SUCCESS;
 
-       sdmac->last_completed = sdmac->desc.cookie;
+       dma_cookie_complete(&sdmac->desc);
        if (sdmac->desc.callback)
                sdmac->desc.callback(sdmac->desc.callback_param);
 }
@@ -544,10 +551,10 @@ static void mxc_sdma_handle_channel(struct sdma_channel *sdmac)
 static irqreturn_t sdma_int_handler(int irq, void *dev_id)
 {
        struct sdma_engine *sdma = dev_id;
-       u32 stat;
+       unsigned long stat;
 
-       stat = __raw_readl(sdma->regs + SDMA_H_INTR);
-       __raw_writel(stat, sdma->regs + SDMA_H_INTR);
+       stat = readl_relaxed(sdma->regs + SDMA_H_INTR);
+       writel_relaxed(stat, sdma->regs + SDMA_H_INTR);
 
        while (stat) {
                int channel = fls(stat) - 1;
@@ -555,7 +562,7 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
 
                mxc_sdma_handle_channel(sdmac);
 
-               stat &= ~(1 << channel);
+               __clear_bit(channel, &stat);
        }
 
        return IRQ_HANDLED;
@@ -663,11 +670,11 @@ static int sdma_load_context(struct sdma_channel *sdmac)
                return load_address;
 
        dev_dbg(sdma->dev, "load_address = %d\n", load_address);
-       dev_dbg(sdma->dev, "wml = 0x%08x\n", sdmac->watermark_level);
+       dev_dbg(sdma->dev, "wml = 0x%08x\n", (u32)sdmac->watermark_level);
        dev_dbg(sdma->dev, "shp_addr = 0x%08x\n", sdmac->shp_addr);
        dev_dbg(sdma->dev, "per_addr = 0x%08x\n", sdmac->per_addr);
-       dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
-       dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
+       dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", (u32)sdmac->event_mask[0]);
+       dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", (u32)sdmac->event_mask[1]);
 
        mutex_lock(&sdma->channel_0_lock);
 
@@ -677,8 +684,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
        /* Send by context the event mask,base address for peripheral
         * and watermark level
         */
-       context->gReg[0] = sdmac->event_mask1;
-       context->gReg[1] = sdmac->event_mask0;
+       context->gReg[0] = sdmac->event_mask[1];
+       context->gReg[1] = sdmac->event_mask[0];
        context->gReg[2] = sdmac->per_addr;
        context->gReg[6] = sdmac->shp_addr;
        context->gReg[7] = sdmac->watermark_level;
@@ -701,7 +708,7 @@ static void sdma_disable_channel(struct sdma_channel *sdmac)
        struct sdma_engine *sdma = sdmac->sdma;
        int channel = sdmac->channel;
 
-       __raw_writel(1 << channel, sdma->regs + SDMA_H_STATSTOP);
+       writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
        sdmac->status = DMA_ERROR;
 }
 
@@ -711,13 +718,13 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
 
        sdma_disable_channel(sdmac);
 
-       sdmac->event_mask0 = 0;
-       sdmac->event_mask1 = 0;
+       sdmac->event_mask[0] = 0;
+       sdmac->event_mask[1] = 0;
        sdmac->shp_addr = 0;
        sdmac->per_addr = 0;
 
        if (sdmac->event_id0) {
-               if (sdmac->event_id0 > 32)
+               if (sdmac->event_id0 >= sdmac->sdma->num_events)
                        return -EINVAL;
                sdma_event_enable(sdmac, sdmac->event_id0);
        }
@@ -740,15 +747,14 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
                        (sdmac->peripheral_type != IMX_DMATYPE_DSP)) {
                /* Handle multiple event channels differently */
                if (sdmac->event_id1) {
-                       sdmac->event_mask1 = 1 << (sdmac->event_id1 % 32);
+                       sdmac->event_mask[1] = BIT(sdmac->event_id1 % 32);
                        if (sdmac->event_id1 > 31)
-                               sdmac->watermark_level |= 1 << 31;
-                       sdmac->event_mask0 = 1 << (sdmac->event_id0 % 32);
+                               __set_bit(31, &sdmac->watermark_level);
+                       sdmac->event_mask[0] = BIT(sdmac->event_id0 % 32);
                        if (sdmac->event_id0 > 31)
-                               sdmac->watermark_level |= 1 << 30;
+                               __set_bit(30, &sdmac->watermark_level);
                } else {
-                       sdmac->event_mask0 = 1 << sdmac->event_id0;
-                       sdmac->event_mask1 = 1 << (sdmac->event_id0 - 32);
+                       __set_bit(sdmac->event_id0, sdmac->event_mask);
                }
                /* Watermark Level */
                sdmac->watermark_level |= sdmac->watermark_level;
@@ -774,7 +780,7 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
                return -EINVAL;
        }
 
-       __raw_writel(priority, sdma->regs + SDMA_CHNPRI_0 + 4 * channel);
+       writel_relaxed(priority, sdma->regs + SDMA_CHNPRI_0 + 4 * channel);
 
        return 0;
 }
@@ -796,8 +802,6 @@ static int sdma_request_channel(struct sdma_channel *sdmac)
        sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
        sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
 
-       clk_enable(sdma->clk);
-
        sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
 
        init_completion(&sdmac->done);
@@ -810,24 +814,6 @@ out:
        return ret;
 }
 
-static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
-{
-       __raw_writel(1 << channel, sdma->regs + SDMA_H_START);
-}
-
-static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdmac)
-{
-       dma_cookie_t cookie = sdmac->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       sdmac->chan.cookie = cookie;
-       sdmac->desc.cookie = cookie;
-
-       return cookie;
-}
-
 static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
 {
        return container_of(chan, struct sdma_channel, chan);
@@ -837,14 +823,11 @@ static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        unsigned long flags;
        struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
-       struct sdma_engine *sdma = sdmac->sdma;
        dma_cookie_t cookie;
 
        spin_lock_irqsave(&sdmac->lock, flags);
 
-       cookie = sdma_assign_cookie(sdmac);
-
-       sdma_enable_channel(sdma, sdmac->channel);
+       cookie = dma_cookie_assign(tx);
 
        spin_unlock_irqrestore(&sdmac->lock, flags);
 
@@ -875,11 +858,14 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
 
        sdmac->peripheral_type = data->peripheral_type;
        sdmac->event_id0 = data->dma_request;
-       ret = sdma_set_channel_priority(sdmac, prio);
+
+       clk_enable(sdmac->sdma->clk);
+
+       ret = sdma_request_channel(sdmac);
        if (ret)
                return ret;
 
-       ret = sdma_request_channel(sdmac);
+       ret = sdma_set_channel_priority(sdmac, prio);
        if (ret)
                return ret;
 
@@ -916,7 +902,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags)
+               unsigned long flags, void *context)
 {
        struct sdma_channel *sdmac = to_sdma_chan(chan);
        struct sdma_engine *sdma = sdmac->sdma;
@@ -1014,7 +1000,8 @@ err_out:
 
 static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
-               size_t period_len, enum dma_transfer_direction direction)
+               size_t period_len, enum dma_transfer_direction direction,
+               void *context)
 {
        struct sdma_channel *sdmac = to_sdma_chan(chan);
        struct sdma_engine *sdma = sdmac->sdma;
@@ -1128,7 +1115,7 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
 
        last_used = chan->cookie;
 
-       dma_set_tx_state(txstate, sdmac->last_completed, last_used,
+       dma_set_tx_state(txstate, chan->completed_cookie, last_used,
                        sdmac->chn_count - sdmac->chn_real_count);
 
        return sdmac->status;
@@ -1136,9 +1123,11 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
 
 static void sdma_issue_pending(struct dma_chan *chan)
 {
-       /*
-        * Nothing to do. We only have a single descriptor
-        */
+       struct sdma_channel *sdmac = to_sdma_chan(chan);
+       struct sdma_engine *sdma = sdmac->sdma;
+
+       if (sdmac->status == DMA_IN_PROGRESS)
+               sdma_enable_channel(sdma, sdmac->channel);
 }
 
 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1        34
@@ -1230,7 +1219,7 @@ static int __init sdma_init(struct sdma_engine *sdma)
        clk_enable(sdma->clk);
 
        /* Be sure SDMA has not started yet */
-       __raw_writel(0, sdma->regs + SDMA_H_C0PTR);
+       writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
 
        sdma->channel_control = dma_alloc_coherent(NULL,
                        MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
@@ -1253,11 +1242,11 @@ static int __init sdma_init(struct sdma_engine *sdma)
 
        /* disable all channels */
        for (i = 0; i < sdma->num_events; i++)
-               __raw_writel(0, sdma->regs + chnenbl_ofs(sdma, i));
+               writel_relaxed(0, sdma->regs + chnenbl_ofs(sdma, i));
 
        /* All channels have priority 0 */
        for (i = 0; i < MAX_DMA_CHANNELS; i++)
-               __raw_writel(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
+               writel_relaxed(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
 
        ret = sdma_request_channel(&sdma->channel[0]);
        if (ret)
@@ -1266,16 +1255,16 @@ static int __init sdma_init(struct sdma_engine *sdma)
        sdma_config_ownership(&sdma->channel[0], false, true, false);
 
        /* Set Command Channel (Channel Zero) */
-       __raw_writel(0x4050, sdma->regs + SDMA_CHN0ADDR);
+       writel_relaxed(0x4050, sdma->regs + SDMA_CHN0ADDR);
 
        /* Set bits of CONFIG register but with static context switching */
        /* FIXME: Check whether to set ACR bit depending on clock ratios */
-       __raw_writel(0, sdma->regs + SDMA_H_CONFIG);
+       writel_relaxed(0, sdma->regs + SDMA_H_CONFIG);
 
-       __raw_writel(ccb_phys, sdma->regs + SDMA_H_C0PTR);
+       writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
        /* Set bits of CONFIG register with given context switching mode */
-       __raw_writel(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+       writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
 
        /* Initializes channel's priorities */
        sdma_set_channel_priority(&sdma->channel[0], 7);
@@ -1367,6 +1356,7 @@ static int __init sdma_probe(struct platform_device *pdev)
                spin_lock_init(&sdmac->lock);
 
                sdmac->chan.device = &sdma->dma_device;
+               dma_cookie_init(&sdmac->chan);
                sdmac->channel = i;
 
                /*
@@ -1387,7 +1377,9 @@ static int __init sdma_probe(struct platform_device *pdev)
                sdma_add_scripts(sdma, pdata->script_addrs);
 
        if (pdata) {
-               sdma_get_firmware(sdma, pdata->fw_name);
+               ret = sdma_get_firmware(sdma, pdata->fw_name);
+               if (ret)
+                       dev_warn(&pdev->dev, "failed to get firmware from platform data\n");
        } else {
                /*
                 * Because that device tree does not encode ROM script address,
@@ -1396,15 +1388,12 @@ static int __init sdma_probe(struct platform_device *pdev)
                 */
                ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
                                              &fw_name);
-               if (ret) {
-                       dev_err(&pdev->dev, "failed to get firmware name\n");
-                       goto err_init;
-               }
-
-               ret = sdma_get_firmware(sdma, fw_name);
-               if (ret) {
-                       dev_err(&pdev->dev, "failed to get firmware\n");
-                       goto err_init;
+               if (ret)
+                       dev_warn(&pdev->dev, "failed to get firmware name\n");
+               else {
+                       ret = sdma_get_firmware(sdma, fw_name);
+                       if (ret)
+                               dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
                }
        }
 
index 74f70aadf9e47313cb23e3bee95781c8f24a2e02..c900ca7aaec4b16d2ad5292c9997ff51d9616492 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/intel_mid_dma.h>
 #include <linux/module.h>
 
+#include "dmaengine.h"
+
 #define MAX_CHAN       4 /*max ch across controllers*/
 #include "intel_mid_dma_regs.h"
 
@@ -288,7 +290,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
        struct intel_mid_dma_lli        *llitem;
        void *param_txd = NULL;
 
-       midc->completed = txd->cookie;
+       dma_cookie_complete(txd);
        callback_txd = txd->callback;
        param_txd = txd->callback_param;
 
@@ -434,14 +436,7 @@ static dma_cookie_t intel_mid_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        dma_cookie_t            cookie;
 
        spin_lock_bh(&midc->lock);
-       cookie = midc->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       midc->chan.cookie = cookie;
-       desc->txd.cookie = cookie;
-
+       cookie = dma_cookie_assign(tx);
 
        if (list_empty(&midc->active_list))
                list_add_tail(&desc->desc_node, &midc->active_list);
@@ -482,31 +477,18 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
                                                dma_cookie_t cookie,
                                                struct dma_tx_state *txstate)
 {
-       struct intel_mid_dma_chan       *midc = to_intel_mid_dma_chan(chan);
-       dma_cookie_t            last_used;
-       dma_cookie_t            last_complete;
-       int                             ret;
+       struct intel_mid_dma_chan *midc = to_intel_mid_dma_chan(chan);
+       enum dma_status ret;
 
-       last_complete = midc->completed;
-       last_used = chan->cookie;
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret != DMA_SUCCESS) {
                spin_lock_bh(&midc->lock);
                midc_scan_descriptors(to_middma_device(chan->device), midc);
                spin_unlock_bh(&midc->lock);
 
-               last_complete = midc->completed;
-               last_used = chan->cookie;
-
-               ret = dma_async_is_complete(cookie, last_complete, last_used);
+               ret = dma_cookie_status(chan, cookie, txstate);
        }
 
-       if (txstate) {
-               txstate->last = last_complete;
-               txstate->used = last_used;
-               txstate->residue = 0;
-       }
        return ret;
 }
 
@@ -732,13 +714,14 @@ err_desc_get:
  * @sg_len: length of sg txn
  * @direction: DMA transfer dirtn
  * @flags: DMA flags
+ * @context: transfer context (ignored)
  *
  * Prepares LLI based periphral transfer
  */
 static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg(
                        struct dma_chan *chan, struct scatterlist *sgl,
                        unsigned int sg_len, enum dma_transfer_direction direction,
-                       unsigned long flags)
+                       unsigned long flags, void *context)
 {
        struct intel_mid_dma_chan *midc = NULL;
        struct intel_mid_dma_slave *mids = NULL;
@@ -832,7 +815,6 @@ static void intel_mid_dma_free_chan_resources(struct dma_chan *chan)
                /*trying to free ch in use!!!!!*/
                pr_err("ERR_MDMA: trying to free ch in use\n");
        }
-       pm_runtime_put(&mid->pdev->dev);
        spin_lock_bh(&midc->lock);
        midc->descs_allocated = 0;
        list_for_each_entry_safe(desc, _desc, &midc->active_list, desc_node) {
@@ -853,6 +835,7 @@ static void intel_mid_dma_free_chan_resources(struct dma_chan *chan)
        /* Disable CH interrupts */
        iowrite32(MASK_INTR_REG(midc->ch_id), mid->dma_base + MASK_BLOCK);
        iowrite32(MASK_INTR_REG(midc->ch_id), mid->dma_base + MASK_ERR);
+       pm_runtime_put(&mid->pdev->dev);
 }
 
 /**
@@ -886,7 +869,7 @@ static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan)
                pm_runtime_put(&mid->pdev->dev);
                return -EIO;
        }
-       midc->completed = chan->cookie = 1;
+       dma_cookie_init(chan);
 
        spin_lock_bh(&midc->lock);
        while (midc->descs_allocated < DESCS_PER_CHANNEL) {
@@ -1056,7 +1039,8 @@ static irqreturn_t intel_mid_dma_interrupt(int irq, void *data)
        }
        err_status &= mid->intr_mask;
        if (err_status) {
-               iowrite32(MASK_INTR_REG(err_status), mid->dma_base + MASK_ERR);
+               iowrite32((err_status << INT_MASK_WE),
+                         mid->dma_base + MASK_ERR);
                call_tasklet = 1;
        }
        if (call_tasklet)
@@ -1118,7 +1102,7 @@ static int mid_setup_dma(struct pci_dev *pdev)
                struct intel_mid_dma_chan *midch = &dma->ch[i];
 
                midch->chan.device = &dma->common;
-               midch->chan.cookie =  1;
+               dma_cookie_init(&midch->chan);
                midch->ch_id = dma->chan_base + i;
                pr_debug("MDMA:Init CH %d, ID %d\n", i, midch->ch_id);
 
index c83d35b97bd8e38a91330854c3d8b10acbe4cedf..1bfa9268feafebb944a7eb32c203d29ca8097afb 100644 (file)
@@ -165,7 +165,6 @@ union intel_mid_dma_cfg_hi {
  * @dma_base: MMIO register space DMA engine base pointer
  * @ch_id: DMA channel id
  * @lock: channel spinlock
- * @completed: DMA cookie
  * @active_list: current active descriptors
  * @queue: current queued up descriptors
  * @free_list: current free descriptors
@@ -183,7 +182,6 @@ struct intel_mid_dma_chan {
        void __iomem            *dma_base;
        int                     ch_id;
        spinlock_t              lock;
-       dma_cookie_t            completed;
        struct list_head        active_list;
        struct list_head        queue;
        struct list_head        free_list;
index a4d6cb0c0343a32c166f3003f65378e5a31da7f1..31493d80e0e9dd0538546703317dbf60abe2247e 100644 (file)
@@ -40,6 +40,8 @@
 #include "registers.h"
 #include "hw.h"
 
+#include "../dmaengine.h"
+
 int ioat_pending_level = 4;
 module_param(ioat_pending_level, int, 0644);
 MODULE_PARM_DESC(ioat_pending_level,
@@ -107,6 +109,7 @@ void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *c
        chan->reg_base = device->reg_base + (0x80 * (idx + 1));
        spin_lock_init(&chan->cleanup_lock);
        chan->common.device = dma;
+       dma_cookie_init(&chan->common);
        list_add_tail(&chan->common.device_node, &dma->channels);
        device->idx[idx] = chan;
        init_timer(&chan->timer);
@@ -235,12 +238,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
 
        spin_lock_bh(&ioat->desc_lock);
        /* cookie incr and addition to used_list must be atomic */
-       cookie = c->cookie;
-       cookie++;
-       if (cookie < 0)
-               cookie = 1;
-       c->cookie = cookie;
-       tx->cookie = cookie;
+       cookie = dma_cookie_assign(tx);
        dev_dbg(to_dev(&ioat->base), "%s: cookie: %d\n", __func__, cookie);
 
        /* write address into NextDescriptor field of last desc in chain */
@@ -603,8 +601,7 @@ static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
                 */
                dump_desc_dbg(ioat, desc);
                if (tx->cookie) {
-                       chan->completed_cookie = tx->cookie;
-                       tx->cookie = 0;
+                       dma_cookie_complete(tx);
                        ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
                        ioat->active -= desc->hw->tx_cnt;
                        if (tx->callback) {
@@ -733,13 +730,15 @@ ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
 {
        struct ioat_chan_common *chan = to_chan_common(c);
        struct ioatdma_device *device = chan->device;
+       enum dma_status ret;
 
-       if (ioat_tx_status(c, cookie, txstate) == DMA_SUCCESS)
-               return DMA_SUCCESS;
+       ret = dma_cookie_status(c, cookie, txstate);
+       if (ret == DMA_SUCCESS)
+               return ret;
 
        device->cleanup_fn((unsigned long) c);
 
-       return ioat_tx_status(c, cookie, txstate);
+       return dma_cookie_status(c, cookie, txstate);
 }
 
 static void ioat1_dma_start_null_desc(struct ioat_dma_chan *ioat)
index 5216c8a92a21327d9787e0dc39de885bbc8f8acb..c7888bccd9740c6cefba7719c1e33cc724a7152d 100644 (file)
@@ -90,7 +90,6 @@ struct ioat_chan_common {
        void __iomem *reg_base;
        unsigned long last_completion;
        spinlock_t cleanup_lock;
-       dma_cookie_t completed_cookie;
        unsigned long state;
        #define IOAT_COMPLETION_PENDING 0
        #define IOAT_COMPLETION_ACK 1
@@ -143,28 +142,6 @@ static inline struct ioat_dma_chan *to_ioat_chan(struct dma_chan *c)
        return container_of(chan, struct ioat_dma_chan, base);
 }
 
-/**
- * ioat_tx_status - poll the status of an ioat transaction
- * @c: channel handle
- * @cookie: transaction identifier
- * @txstate: if set, updated with the transaction state
- */
-static inline enum dma_status
-ioat_tx_status(struct dma_chan *c, dma_cookie_t cookie,
-                struct dma_tx_state *txstate)
-{
-       struct ioat_chan_common *chan = to_chan_common(c);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
-
-       last_used = c->cookie;
-       last_complete = chan->completed_cookie;
-
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
-       return dma_async_is_complete(cookie, last_complete, last_used);
-}
-
 /* wrapper around hardware descriptor format + additional software fields */
 
 /**
index 5d65f8377971d697a0452988a59c5bb35639ba8e..e8e110ff3d965547b03f7bbf80cddcb58911a031 100644 (file)
@@ -41,6 +41,8 @@
 #include "registers.h"
 #include "hw.h"
 
+#include "../dmaengine.h"
+
 int ioat_ring_alloc_order = 8;
 module_param(ioat_ring_alloc_order, int, 0644);
 MODULE_PARM_DESC(ioat_ring_alloc_order,
@@ -147,8 +149,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
                dump_desc_dbg(ioat, desc);
                if (tx->cookie) {
                        ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
-                       chan->completed_cookie = tx->cookie;
-                       tx->cookie = 0;
+                       dma_cookie_complete(tx);
                        if (tx->callback) {
                                tx->callback(tx->callback_param);
                                tx->callback = NULL;
@@ -398,13 +399,9 @@ static dma_cookie_t ioat2_tx_submit_unlock(struct dma_async_tx_descriptor *tx)
        struct dma_chan *c = tx->chan;
        struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
        struct ioat_chan_common *chan = &ioat->base;
-       dma_cookie_t cookie = c->cookie;
+       dma_cookie_t cookie;
 
-       cookie++;
-       if (cookie < 0)
-               cookie = 1;
-       tx->cookie = cookie;
-       c->cookie = cookie;
+       cookie = dma_cookie_assign(tx);
        dev_dbg(to_dev(&ioat->base), "%s: cookie: %d\n", __func__, cookie);
 
        if (!test_and_set_bit(IOAT_COMPLETION_PENDING, &chan->state))
index f519c93a61e78c4778afeebe7984c4b45a44acc3..2c4476c0e405be9ce3b547b6a0da7cc814eecc07 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/prefetch.h>
+#include "../dmaengine.h"
 #include "registers.h"
 #include "hw.h"
 #include "dma.h"
@@ -277,9 +278,8 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
                dump_desc_dbg(ioat, desc);
                tx = &desc->txd;
                if (tx->cookie) {
-                       chan->completed_cookie = tx->cookie;
+                       dma_cookie_complete(tx);
                        ioat3_dma_unmap(ioat, desc, idx + i);
-                       tx->cookie = 0;
                        if (tx->callback) {
                                tx->callback(tx->callback_param);
                                tx->callback = NULL;
@@ -411,13 +411,15 @@ ioat3_tx_status(struct dma_chan *c, dma_cookie_t cookie,
                struct dma_tx_state *txstate)
 {
        struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
+       enum dma_status ret;
 
-       if (ioat_tx_status(c, cookie, txstate) == DMA_SUCCESS)
-               return DMA_SUCCESS;
+       ret = dma_cookie_status(c, cookie, txstate);
+       if (ret == DMA_SUCCESS)
+               return ret;
 
        ioat3_cleanup(ioat);
 
-       return ioat_tx_status(c, cookie, txstate);
+       return dma_cookie_status(c, cookie, txstate);
 }
 
 static struct dma_async_tx_descriptor *
index faf88b7e1e71d4d0385b9f1c9038429a774ff826..da6c4c2c066a96b68cdb0765ba4e017112f1c7a6 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <mach/adma.h>
 
+#include "dmaengine.h"
+
 #define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
 #define to_iop_adma_device(dev) \
        container_of(dev, struct iop_adma_device, common)
@@ -317,7 +319,7 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
        }
 
        if (cookie > 0) {
-               iop_chan->completed_cookie = cookie;
+               iop_chan->common.completed_cookie = cookie;
                pr_debug("\tcompleted cookie %d\n", cookie);
        }
 }
@@ -438,18 +440,6 @@ retry:
        return NULL;
 }
 
-static dma_cookie_t
-iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
-       struct iop_adma_desc_slot *desc)
-{
-       dma_cookie_t cookie = iop_chan->common.cookie;
-       cookie++;
-       if (cookie < 0)
-               cookie = 1;
-       iop_chan->common.cookie = desc->async_tx.cookie = cookie;
-       return cookie;
-}
-
 static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
 {
        dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
@@ -477,7 +467,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
        slots_per_op = grp_start->slots_per_op;
 
        spin_lock_bh(&iop_chan->lock);
-       cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
+       cookie = dma_cookie_assign(tx);
 
        old_chain_tail = list_entry(iop_chan->chain.prev,
                struct iop_adma_desc_slot, chain_node);
@@ -904,24 +894,15 @@ static enum dma_status iop_adma_status(struct dma_chan *chan,
                                        struct dma_tx_state *txstate)
 {
        struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
-       enum dma_status ret;
-
-       last_used = chan->cookie;
-       last_complete = iop_chan->completed_cookie;
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       int ret;
+
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret == DMA_SUCCESS)
                return ret;
 
        iop_adma_slot_cleanup(iop_chan);
 
-       last_used = chan->cookie;
-       last_complete = iop_chan->completed_cookie;
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
-       return dma_async_is_complete(cookie, last_complete, last_used);
+       return dma_cookie_status(chan, cookie, txstate);
 }
 
 static irqreturn_t iop_adma_eot_handler(int irq, void *data)
@@ -1565,6 +1546,7 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&iop_chan->chain);
        INIT_LIST_HEAD(&iop_chan->all_slots);
        iop_chan->common.device = dma_dev;
+       dma_cookie_init(&iop_chan->common);
        list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
 
        if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
@@ -1642,16 +1624,12 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
                iop_desc_set_dest_addr(grp_start, iop_chan, 0);
                iop_desc_set_memcpy_src_addr(grp_start, 0);
 
-               cookie = iop_chan->common.cookie;
-               cookie++;
-               if (cookie <= 1)
-                       cookie = 2;
+               cookie = dma_cookie_assign(&sw_desc->async_tx);
 
                /* initialize the completed cookie to be less than
                 * the most recently used cookie
                 */
-               iop_chan->completed_cookie = cookie - 1;
-               iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+               iop_chan->common.completed_cookie = cookie - 1;
 
                /* channel should not be busy */
                BUG_ON(iop_chan_is_busy(iop_chan));
@@ -1699,16 +1677,12 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
                iop_desc_set_xor_src_addr(grp_start, 0, 0);
                iop_desc_set_xor_src_addr(grp_start, 1, 0);
 
-               cookie = iop_chan->common.cookie;
-               cookie++;
-               if (cookie <= 1)
-                       cookie = 2;
+               cookie = dma_cookie_assign(&sw_desc->async_tx);
 
                /* initialize the completed cookie to be less than
                 * the most recently used cookie
                 */
-               iop_chan->completed_cookie = cookie - 1;
-               iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+               iop_chan->common.completed_cookie = cookie - 1;
 
                /* channel should not be busy */
                BUG_ON(iop_chan_is_busy(iop_chan));
index 6212b16e8cf21ea32ae05732ae1f3b1147b134b8..62e3f8ec2461f5584fabe343426f7654d678922f 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <mach/ipu.h>
 
+#include "../dmaengine.h"
 #include "ipu_intern.h"
 
 #define FS_VF_IN_VALID 0x00000002
@@ -866,14 +867,7 @@ static dma_cookie_t idmac_tx_submit(struct dma_async_tx_descriptor *tx)
 
        dev_dbg(dev, "Submitting sg %p\n", &desc->sg[0]);
 
-       cookie = ichan->dma_chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       /* from dmaengine.h: "last cookie value returned to client" */
-       ichan->dma_chan.cookie = cookie;
-       tx->cookie = cookie;
+       cookie = dma_cookie_assign(tx);
 
        /* ipu->lock can be taken under ichan->lock, but not v.v. */
        spin_lock_irqsave(&ichan->lock, flags);
@@ -1295,7 +1289,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
        /* Flip the active buffer - even if update above failed */
        ichan->active_buffer = !ichan->active_buffer;
        if (done)
-               ichan->completed = desc->txd.cookie;
+               dma_cookie_complete(&desc->txd);
 
        callback = desc->txd.callback;
        callback_param = desc->txd.callback_param;
@@ -1341,7 +1335,8 @@ static void ipu_gc_tasklet(unsigned long arg)
 /* Allocate and initialise a transfer descriptor. */
 static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan,
                struct scatterlist *sgl, unsigned int sg_len,
-               enum dma_transfer_direction direction, unsigned long tx_flags)
+               enum dma_transfer_direction direction, unsigned long tx_flags,
+               void *context)
 {
        struct idmac_channel *ichan = to_idmac_chan(chan);
        struct idmac_tx_desc *desc = NULL;
@@ -1510,8 +1505,7 @@ static int idmac_alloc_chan_resources(struct dma_chan *chan)
        BUG_ON(chan->client_count > 1);
        WARN_ON(ichan->status != IPU_CHANNEL_FREE);
 
-       chan->cookie            = 1;
-       ichan->completed        = -ENXIO;
+       dma_cookie_init(chan);
 
        ret = ipu_irq_map(chan->chan_id);
        if (ret < 0)
@@ -1600,9 +1594,7 @@ static void idmac_free_chan_resources(struct dma_chan *chan)
 static enum dma_status idmac_tx_status(struct dma_chan *chan,
                       dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
-       struct idmac_channel *ichan = to_idmac_chan(chan);
-
-       dma_set_tx_state(txstate, ichan->completed, chan->cookie, 0);
+       dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, 0);
        if (cookie != chan->cookie)
                return DMA_ERROR;
        return DMA_SUCCESS;
@@ -1638,11 +1630,10 @@ static int __init ipu_idmac_init(struct ipu *ipu)
 
                ichan->status           = IPU_CHANNEL_FREE;
                ichan->sec_chan_en      = false;
-               ichan->completed        = -ENXIO;
                snprintf(ichan->eof_name, sizeof(ichan->eof_name), "IDMAC EOF %d", i);
 
                dma_chan->device        = &idmac->dma;
-               dma_chan->cookie        = 1;
+               dma_cookie_init(dma_chan);
                dma_chan->chan_id       = i;
                list_add_tail(&dma_chan->device_node, &dma->channels);
        }
index 4d6d4cf669496ff0afc65d5dee450452b143a2c6..2ab0a3d0eed53eb107f475944b97a339e4419a77 100644 (file)
@@ -44,6 +44,8 @@
 
 #include <linux/random.h>
 
+#include "dmaengine.h"
+
 /* Number of DMA Transfer descriptors allocated per channel */
 #define MPC_DMA_DESCRIPTORS    64
 
@@ -188,7 +190,6 @@ struct mpc_dma_chan {
        struct list_head                completed;
        struct mpc_dma_tcd              *tcd;
        dma_addr_t                      tcd_paddr;
-       dma_cookie_t                    completed_cookie;
 
        /* Lock for this structure */
        spinlock_t                      lock;
@@ -365,7 +366,7 @@ static void mpc_dma_process_completed(struct mpc_dma *mdma)
                /* Free descriptors */
                spin_lock_irqsave(&mchan->lock, flags);
                list_splice_tail_init(&list, &mchan->free);
-               mchan->completed_cookie = last_cookie;
+               mchan->chan.completed_cookie = last_cookie;
                spin_unlock_irqrestore(&mchan->lock, flags);
        }
 }
@@ -438,13 +439,7 @@ static dma_cookie_t mpc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
                mpc_dma_execute(mchan);
 
        /* Update cookie */
-       cookie = mchan->chan.cookie + 1;
-       if (cookie <= 0)
-               cookie = 1;
-
-       mchan->chan.cookie = cookie;
-       mdesc->desc.cookie = cookie;
-
+       cookie = dma_cookie_assign(txd);
        spin_unlock_irqrestore(&mchan->lock, flags);
 
        return cookie;
@@ -562,17 +557,14 @@ mpc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
               struct dma_tx_state *txstate)
 {
        struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+       enum dma_status ret;
        unsigned long flags;
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
 
        spin_lock_irqsave(&mchan->lock, flags);
-       last_used = mchan->chan.cookie;
-       last_complete = mchan->completed_cookie;
+       ret = dma_cookie_status(chan, cookie, txstate);
        spin_unlock_irqrestore(&mchan->lock, flags);
 
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-       return dma_async_is_complete(cookie, last_complete, last_used);
+       return ret;
 }
 
 /* Prepare descriptor for memory to memory copy */
@@ -741,8 +733,7 @@ static int __devinit mpc_dma_probe(struct platform_device *op)
                mchan = &mdma->channels[i];
 
                mchan->chan.device = dma;
-               mchan->chan.cookie = 1;
-               mchan->completed_cookie = mchan->chan.cookie;
+               dma_cookie_init(&mchan->chan);
 
                INIT_LIST_HEAD(&mchan->free);
                INIT_LIST_HEAD(&mchan->prepared);
index e779b434af450fedc9f11bfc4db753689cce1ee9..fa5d55fea46cc4829ba55b84a53cb42baafe81c9 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/platform_device.h>
 #include <linux/memory.h>
 #include <plat/mv_xor.h>
+
+#include "dmaengine.h"
 #include "mv_xor.h"
 
 static void mv_xor_issue_pending(struct dma_chan *chan);
@@ -435,7 +437,7 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
        }
 
        if (cookie > 0)
-               mv_chan->completed_cookie = cookie;
+               mv_chan->common.completed_cookie = cookie;
 }
 
 static void
@@ -534,18 +536,6 @@ retry:
        return NULL;
 }
 
-static dma_cookie_t
-mv_desc_assign_cookie(struct mv_xor_chan *mv_chan,
-                     struct mv_xor_desc_slot *desc)
-{
-       dma_cookie_t cookie = mv_chan->common.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-       mv_chan->common.cookie = desc->async_tx.cookie = cookie;
-       return cookie;
-}
-
 /************************ DMA engine API functions ****************************/
 static dma_cookie_t
 mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
@@ -563,7 +553,7 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
        grp_start = sw_desc->group_head;
 
        spin_lock_bh(&mv_chan->lock);
-       cookie = mv_desc_assign_cookie(mv_chan, sw_desc);
+       cookie = dma_cookie_assign(tx);
 
        if (list_empty(&mv_chan->chain))
                list_splice_init(&sw_desc->tx_list, &mv_chan->chain);
@@ -820,27 +810,16 @@ static enum dma_status mv_xor_status(struct dma_chan *chan,
                                          struct dma_tx_state *txstate)
 {
        struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
        enum dma_status ret;
 
-       last_used = chan->cookie;
-       last_complete = mv_chan->completed_cookie;
-       mv_chan->is_complete_cookie = cookie;
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret == DMA_SUCCESS) {
                mv_xor_clean_completed_slots(mv_chan);
                return ret;
        }
        mv_xor_slot_cleanup(mv_chan);
 
-       last_used = chan->cookie;
-       last_complete = mv_chan->completed_cookie;
-
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-       return dma_async_is_complete(cookie, last_complete, last_used);
+       return dma_cookie_status(chan, cookie, txstate);
 }
 
 static void mv_dump_xor_regs(struct mv_xor_chan *chan)
@@ -1214,6 +1193,7 @@ static int __devinit mv_xor_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&mv_chan->completed_slots);
        INIT_LIST_HEAD(&mv_chan->all_slots);
        mv_chan->common.device = dma_dev;
+       dma_cookie_init(&mv_chan->common);
 
        list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
 
index 977b592e976bfa9eea31b64cb0ef5aa8c1ff6b49..654876b7ba1deae84a06f89cdf617b153d4315ef 100644 (file)
@@ -78,7 +78,6 @@ struct mv_xor_device {
 /**
  * struct mv_xor_chan - internal representation of a XOR channel
  * @pending: allows batching of hardware operations
- * @completed_cookie: identifier for the most recently completed operation
  * @lock: serializes enqueue/dequeue operations to the descriptors pool
  * @mmr_base: memory mapped register base
  * @idx: the index of the xor channel
@@ -93,7 +92,6 @@ struct mv_xor_device {
  */
 struct mv_xor_chan {
        int                     pending;
-       dma_cookie_t            completed_cookie;
        spinlock_t              lock; /* protects the descriptor slot pool */
        void __iomem            *mmr_base;
        unsigned int            idx;
@@ -109,7 +107,6 @@ struct mv_xor_chan {
 #ifdef USE_TIMER
        unsigned long           cleanup_time;
        u32                     current_on_last_cleanup;
-       dma_cookie_t            is_complete_cookie;
 #endif
 };
 
index b06cd4ca626fb4fd93d5ab3b7fedddbfd6ea6c25..65334c49b71e92bb3c73c01306a98c86eb90b732 100644 (file)
@@ -28,6 +28,8 @@
 #include <mach/dma.h>
 #include <mach/common.h>
 
+#include "dmaengine.h"
+
 /*
  * NOTE: The term "PIO" throughout the mxs-dma implementation means
  * PIO mode of mxs apbh-dma and apbx-dma.  With this working mode,
@@ -111,7 +113,6 @@ struct mxs_dma_chan {
        struct mxs_dma_ccw              *ccw;
        dma_addr_t                      ccw_phys;
        int                             desc_count;
-       dma_cookie_t                    last_completed;
        enum dma_status                 status;
        unsigned int                    flags;
 #define MXS_DMA_SG_LOOP                        (1 << 0)
@@ -193,19 +194,6 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
        mxs_chan->status = DMA_IN_PROGRESS;
 }
 
-static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
-{
-       dma_cookie_t cookie = mxs_chan->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       mxs_chan->chan.cookie = cookie;
-       mxs_chan->desc.cookie = cookie;
-
-       return cookie;
-}
-
 static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
 {
        return container_of(chan, struct mxs_dma_chan, chan);
@@ -217,7 +205,7 @@ static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 
        mxs_dma_enable_chan(mxs_chan);
 
-       return mxs_dma_assign_cookie(mxs_chan);
+       return dma_cookie_assign(tx);
 }
 
 static void mxs_dma_tasklet(unsigned long data)
@@ -274,7 +262,7 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
                stat1 &= ~(1 << channel);
 
                if (mxs_chan->status == DMA_SUCCESS)
-                       mxs_chan->last_completed = mxs_chan->desc.cookie;
+                       dma_cookie_complete(&mxs_chan->desc);
 
                /* schedule tasklet on this channel */
                tasklet_schedule(&mxs_chan->tasklet);
@@ -352,7 +340,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
 static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long append)
+               unsigned long append, void *context)
 {
        struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -447,7 +435,8 @@ err_out:
 
 static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
-               size_t period_len, enum dma_transfer_direction direction)
+               size_t period_len, enum dma_transfer_direction direction,
+               void *context)
 {
        struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -538,7 +527,7 @@ static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
        dma_cookie_t last_used;
 
        last_used = chan->cookie;
-       dma_set_tx_state(txstate, mxs_chan->last_completed, last_used, 0);
+       dma_set_tx_state(txstate, chan->completed_cookie, last_used, 0);
 
        return mxs_chan->status;
 }
@@ -630,6 +619,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev)
 
                mxs_chan->mxs_dma = mxs_dma;
                mxs_chan->chan.device = &mxs_dma->dma_device;
+               dma_cookie_init(&mxs_chan->chan);
 
                tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet,
                             (unsigned long) mxs_chan);
index 823f58179f9d46a8a169dbbaf7551b1d91ec5f28..65c0495a6d40b74a1f0d7dc659f4ff72ec7c4c63 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/module.h>
 #include <linux/pch_dma.h>
 
+#include "dmaengine.h"
+
 #define DRV_NAME "pch-dma"
 
 #define DMA_CTL0_DISABLE               0x0
@@ -105,7 +107,6 @@ struct pch_dma_chan {
 
        spinlock_t              lock;
 
-       dma_cookie_t            completed_cookie;
        struct list_head        active_list;
        struct list_head        queue;
        struct list_head        free_list;
@@ -416,20 +417,6 @@ static void pdc_advance_work(struct pch_dma_chan *pd_chan)
        }
 }
 
-static dma_cookie_t pdc_assign_cookie(struct pch_dma_chan *pd_chan,
-                                     struct pch_dma_desc *desc)
-{
-       dma_cookie_t cookie = pd_chan->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       pd_chan->chan.cookie = cookie;
-       desc->txd.cookie = cookie;
-
-       return cookie;
-}
-
 static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd)
 {
        struct pch_dma_desc *desc = to_pd_desc(txd);
@@ -437,7 +424,7 @@ static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd)
        dma_cookie_t cookie;
 
        spin_lock(&pd_chan->lock);
-       cookie = pdc_assign_cookie(pd_chan, desc);
+       cookie = dma_cookie_assign(txd);
 
        if (list_empty(&pd_chan->active_list)) {
                list_add_tail(&desc->desc_node, &pd_chan->active_list);
@@ -544,7 +531,7 @@ static int pd_alloc_chan_resources(struct dma_chan *chan)
        spin_lock_irq(&pd_chan->lock);
        list_splice(&tmp_list, &pd_chan->free_list);
        pd_chan->descs_allocated = i;
-       pd_chan->completed_cookie = chan->cookie = 1;
+       dma_cookie_init(chan);
        spin_unlock_irq(&pd_chan->lock);
 
        pdc_enable_irq(chan, 1);
@@ -578,19 +565,12 @@ static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                                    struct dma_tx_state *txstate)
 {
        struct pch_dma_chan *pd_chan = to_pd_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_completed;
-       int ret;
+       enum dma_status ret;
 
        spin_lock_irq(&pd_chan->lock);
-       last_completed = pd_chan->completed_cookie;
-       last_used = chan->cookie;
+       ret = dma_cookie_status(chan, cookie, txstate);
        spin_unlock_irq(&pd_chan->lock);
 
-       ret = dma_async_is_complete(cookie, last_completed, last_used);
-
-       dma_set_tx_state(txstate, last_completed, last_used, 0);
-
        return ret;
 }
 
@@ -607,7 +587,8 @@ static void pd_issue_pending(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
                        struct scatterlist *sgl, unsigned int sg_len,
-                       enum dma_transfer_direction direction, unsigned long flags)
+                       enum dma_transfer_direction direction, unsigned long flags,
+                       void *context)
 {
        struct pch_dma_chan *pd_chan = to_pd_chan(chan);
        struct pch_dma_slave *pd_slave = chan->private;
@@ -932,7 +913,7 @@ static int __devinit pch_dma_probe(struct pci_dev *pdev,
                struct pch_dma_chan *pd_chan = &pd->channels[i];
 
                pd_chan->chan.device = &pd->dma;
-               pd_chan->chan.cookie = 1;
+               dma_cookie_init(&pd_chan->chan);
 
                pd_chan->membase = &regs->desc[i];
 
index 16b66c827f19984c47401b89d70338570c446f18..282caf118be819c5e9257754a369efd292607951 100644 (file)
@@ -1,4 +1,6 @@
-/* linux/drivers/dma/pl330.c
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
  *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  * (at your option) any later version.
  */
 
-#include <linux/io.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/dmaengine.h>
-#include <linux/interrupt.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-#include <linux/pm_runtime.h>
-#include <linux/scatterlist.h>
-#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
+#include <linux/of.h>
+
+#include "dmaengine.h"
+#define PL330_MAX_CHAN         8
+#define PL330_MAX_IRQS         32
+#define PL330_MAX_PERI         32
+
+enum pl330_srccachectrl {
+       SCCTRL0,        /* Noncacheable and nonbufferable */
+       SCCTRL1,        /* Bufferable only */
+       SCCTRL2,        /* Cacheable, but do not allocate */
+       SCCTRL3,        /* Cacheable and bufferable, but do not allocate */
+       SINVALID1,
+       SINVALID2,
+       SCCTRL6,        /* Cacheable write-through, allocate on reads only */
+       SCCTRL7,        /* Cacheable write-back, allocate on reads only */
+};
+
+enum pl330_dstcachectrl {
+       DCCTRL0,        /* Noncacheable and nonbufferable */
+       DCCTRL1,        /* Bufferable only */
+       DCCTRL2,        /* Cacheable, but do not allocate */
+       DCCTRL3,        /* Cacheable and bufferable, but do not allocate */
+       DINVALID1,      /* AWCACHE = 0x1000 */
+       DINVALID2,
+       DCCTRL6,        /* Cacheable write-through, allocate on writes only */
+       DCCTRL7,        /* Cacheable write-back, allocate on writes only */
+};
+
+enum pl330_byteswap {
+       SWAP_NO,
+       SWAP_2,
+       SWAP_4,
+       SWAP_8,
+       SWAP_16,
+};
+
+enum pl330_reqtype {
+       MEMTOMEM,
+       MEMTODEV,
+       DEVTOMEM,
+       DEVTODEV,
+};
+
+/* Register and Bit field Definitions */
+#define DS                     0x0
+#define DS_ST_STOP             0x0
+#define DS_ST_EXEC             0x1
+#define DS_ST_CMISS            0x2
+#define DS_ST_UPDTPC           0x3
+#define DS_ST_WFE              0x4
+#define DS_ST_ATBRR            0x5
+#define DS_ST_QBUSY            0x6
+#define DS_ST_WFP              0x7
+#define DS_ST_KILL             0x8
+#define DS_ST_CMPLT            0x9
+#define DS_ST_FLTCMP           0xe
+#define DS_ST_FAULT            0xf
+
+#define DPC                    0x4
+#define INTEN                  0x20
+#define ES                     0x24
+#define INTSTATUS              0x28
+#define INTCLR                 0x2c
+#define FSM                    0x30
+#define FSC                    0x34
+#define FTM                    0x38
+
+#define _FTC                   0x40
+#define FTC(n)                 (_FTC + (n)*0x4)
+
+#define _CS                    0x100
+#define CS(n)                  (_CS + (n)*0x8)
+#define CS_CNS                 (1 << 21)
+
+#define _CPC                   0x104
+#define CPC(n)                 (_CPC + (n)*0x8)
+
+#define _SA                    0x400
+#define SA(n)                  (_SA + (n)*0x20)
+
+#define _DA                    0x404
+#define DA(n)                  (_DA + (n)*0x20)
+
+#define _CC                    0x408
+#define CC(n)                  (_CC + (n)*0x20)
+
+#define CC_SRCINC              (1 << 0)
+#define CC_DSTINC              (1 << 14)
+#define CC_SRCPRI              (1 << 8)
+#define CC_DSTPRI              (1 << 22)
+#define CC_SRCNS               (1 << 9)
+#define CC_DSTNS               (1 << 23)
+#define CC_SRCIA               (1 << 10)
+#define CC_DSTIA               (1 << 24)
+#define CC_SRCBRSTLEN_SHFT     4
+#define CC_DSTBRSTLEN_SHFT     18
+#define CC_SRCBRSTSIZE_SHFT    1
+#define CC_DSTBRSTSIZE_SHFT    15
+#define CC_SRCCCTRL_SHFT       11
+#define CC_SRCCCTRL_MASK       0x7
+#define CC_DSTCCTRL_SHFT       25
+#define CC_DRCCCTRL_MASK       0x7
+#define CC_SWAP_SHFT           28
+
+#define _LC0                   0x40c
+#define LC0(n)                 (_LC0 + (n)*0x20)
+
+#define _LC1                   0x410
+#define LC1(n)                 (_LC1 + (n)*0x20)
+
+#define DBGSTATUS              0xd00
+#define DBG_BUSY               (1 << 0)
+
+#define DBGCMD                 0xd04
+#define DBGINST0               0xd08
+#define DBGINST1               0xd0c
+
+#define CR0                    0xe00
+#define CR1                    0xe04
+#define CR2                    0xe08
+#define CR3                    0xe0c
+#define CR4                    0xe10
+#define CRD                    0xe14
+
+#define PERIPH_ID              0xfe0
+#define PERIPH_REV_SHIFT       20
+#define PERIPH_REV_MASK                0xf
+#define PERIPH_REV_R0P0                0
+#define PERIPH_REV_R1P0                1
+#define PERIPH_REV_R1P1                2
+#define PCELL_ID               0xff0
+
+#define CR0_PERIPH_REQ_SET     (1 << 0)
+#define CR0_BOOT_EN_SET                (1 << 1)
+#define CR0_BOOT_MAN_NS                (1 << 2)
+#define CR0_NUM_CHANS_SHIFT    4
+#define CR0_NUM_CHANS_MASK     0x7
+#define CR0_NUM_PERIPH_SHIFT   12
+#define CR0_NUM_PERIPH_MASK    0x1f
+#define CR0_NUM_EVENTS_SHIFT   17
+#define CR0_NUM_EVENTS_MASK    0x1f
+
+#define CR1_ICACHE_LEN_SHIFT   0
+#define CR1_ICACHE_LEN_MASK    0x7
+#define CR1_NUM_ICACHELINES_SHIFT      4
+#define CR1_NUM_ICACHELINES_MASK       0xf
+
+#define CRD_DATA_WIDTH_SHIFT   0
+#define CRD_DATA_WIDTH_MASK    0x7
+#define CRD_WR_CAP_SHIFT       4
+#define CRD_WR_CAP_MASK                0x7
+#define CRD_WR_Q_DEP_SHIFT     8
+#define CRD_WR_Q_DEP_MASK      0xf
+#define CRD_RD_CAP_SHIFT       12
+#define CRD_RD_CAP_MASK                0x7
+#define CRD_RD_Q_DEP_SHIFT     16
+#define CRD_RD_Q_DEP_MASK      0xf
+#define CRD_DATA_BUFF_SHIFT    20
+#define CRD_DATA_BUFF_MASK     0x3ff
+
+#define PART                   0x330
+#define DESIGNER               0x41
+#define REVISION               0x0
+#define INTEG_CFG              0x0
+#define PERIPH_ID_VAL          ((PART << 0) | (DESIGNER << 12))
+
+#define PCELL_ID_VAL           0xb105f00d
+
+#define PL330_STATE_STOPPED            (1 << 0)
+#define PL330_STATE_EXECUTING          (1 << 1)
+#define PL330_STATE_WFE                        (1 << 2)
+#define PL330_STATE_FAULTING           (1 << 3)
+#define PL330_STATE_COMPLETING         (1 << 4)
+#define PL330_STATE_WFP                        (1 << 5)
+#define PL330_STATE_KILLING            (1 << 6)
+#define PL330_STATE_FAULT_COMPLETING   (1 << 7)
+#define PL330_STATE_CACHEMISS          (1 << 8)
+#define PL330_STATE_UPDTPC             (1 << 9)
+#define PL330_STATE_ATBARRIER          (1 << 10)
+#define PL330_STATE_QUEUEBUSY          (1 << 11)
+#define PL330_STATE_INVALID            (1 << 15)
+
+#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \
+                               | PL330_STATE_WFE | PL330_STATE_FAULTING)
+
+#define CMD_DMAADDH            0x54
+#define CMD_DMAEND             0x00
+#define CMD_DMAFLUSHP          0x35
+#define CMD_DMAGO              0xa0
+#define CMD_DMALD              0x04
+#define CMD_DMALDP             0x25
+#define CMD_DMALP              0x20
+#define CMD_DMALPEND           0x28
+#define CMD_DMAKILL            0x01
+#define CMD_DMAMOV             0xbc
+#define CMD_DMANOP             0x18
+#define CMD_DMARMB             0x12
+#define CMD_DMASEV             0x34
+#define CMD_DMAST              0x08
+#define CMD_DMASTP             0x29
+#define CMD_DMASTZ             0x0c
+#define CMD_DMAWFE             0x36
+#define CMD_DMAWFP             0x30
+#define CMD_DMAWMB             0x13
+
+#define SZ_DMAADDH             3
+#define SZ_DMAEND              1
+#define SZ_DMAFLUSHP           2
+#define SZ_DMALD               1
+#define SZ_DMALDP              2
+#define SZ_DMALP               2
+#define SZ_DMALPEND            2
+#define SZ_DMAKILL             1
+#define SZ_DMAMOV              6
+#define SZ_DMANOP              1
+#define SZ_DMARMB              1
+#define SZ_DMASEV              2
+#define SZ_DMAST               1
+#define SZ_DMASTP              2
+#define SZ_DMASTZ              1
+#define SZ_DMAWFE              2
+#define SZ_DMAWFP              2
+#define SZ_DMAWMB              1
+#define SZ_DMAGO               6
+
+#define BRST_LEN(ccr)          ((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1)
+#define BRST_SIZE(ccr)         (1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7))
+
+#define BYTE_TO_BURST(b, ccr)  ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr))
+#define BURST_TO_BYTE(c, ccr)  ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr))
+
+/*
+ * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req
+ * at 1byte/burst for P<->M and M<->M respectively.
+ * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req
+ * should be enough for P<->M and M<->M respectively.
+ */
+#define MCODE_BUFF_PER_REQ     256
+
+/* If the _pl330_req is available to the client */
+#define IS_FREE(req)   (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
+
+/* Use this _only_ to wait on transient states */
+#define UNTIL(t, s)    while (!(_state(t) & (s))) cpu_relax();
+
+#ifdef PL330_DEBUG_MCGEN
+static unsigned cmd_line;
+#define PL330_DBGCMD_DUMP(off, x...)   do { \
+                                               printk("%x:", cmd_line); \
+                                               printk(x); \
+                                               cmd_line += off; \
+                                       } while (0)
+#define PL330_DBGMC_START(addr)                (cmd_line = addr)
+#else
+#define PL330_DBGCMD_DUMP(off, x...)   do {} while (0)
+#define PL330_DBGMC_START(addr)                do {} while (0)
+#endif
+
+/* The number of default descriptors */
+
+#define NR_DEFAULT_DESC        16
+
+/* Populated by the PL330 core driver for DMA API driver's info */
+struct pl330_config {
+       u32     periph_id;
+       u32     pcell_id;
+#define DMAC_MODE_NS   (1 << 0)
+       unsigned int    mode;
+       unsigned int    data_bus_width:10; /* In number of bits */
+       unsigned int    data_buf_dep:10;
+       unsigned int    num_chan:4;
+       unsigned int    num_peri:6;
+       u32             peri_ns;
+       unsigned int    num_events:6;
+       u32             irq_ns;
+};
+
+/* Handle to the DMAC provided to the PL330 core */
+struct pl330_info {
+       /* Owning device */
+       struct device *dev;
+       /* Size of MicroCode buffers for each channel. */
+       unsigned mcbufsz;
+       /* ioremap'ed address of PL330 registers. */
+       void __iomem    *base;
+       /* Client can freely use it. */
+       void    *client_data;
+       /* PL330 core data, Client must not touch it. */
+       void    *pl330_data;
+       /* Populated by the PL330 core driver during pl330_add */
+       struct pl330_config     pcfg;
+       /*
+        * If the DMAC has some reset mechanism, then the
+        * client may want to provide pointer to the method.
+        */
+       void (*dmac_reset)(struct pl330_info *pi);
+};
+
+/**
+ * Request Configuration.
+ * The PL330 core does not modify this and uses the last
+ * working configuration if the request doesn't provide any.
+ *
+ * The Client may want to provide this info only for the
+ * first request and a request with new settings.
+ */
+struct pl330_reqcfg {
+       /* Address Incrementing */
+       unsigned dst_inc:1;
+       unsigned src_inc:1;
+
+       /*
+        * For now, the SRC & DST protection levels
+        * and burst size/length are assumed same.
+        */
+       bool nonsecure;
+       bool privileged;
+       bool insnaccess;
+       unsigned brst_len:5;
+       unsigned brst_size:3; /* in power of 2 */
+
+       enum pl330_dstcachectrl dcctl;
+       enum pl330_srccachectrl scctl;
+       enum pl330_byteswap swap;
+       struct pl330_config *pcfg;
+};
+
+/*
+ * One cycle of DMAC operation.
+ * There may be more than one xfer in a request.
+ */
+struct pl330_xfer {
+       u32 src_addr;
+       u32 dst_addr;
+       /* Size to xfer */
+       u32 bytes;
+       /*
+        * Pointer to next xfer in the list.
+        * The last xfer in the req must point to NULL.
+        */
+       struct pl330_xfer *next;
+};
+
+/* The xfer callbacks are made with one of these arguments. */
+enum pl330_op_err {
+       /* The all xfers in the request were success. */
+       PL330_ERR_NONE,
+       /* If req aborted due to global error. */
+       PL330_ERR_ABORT,
+       /* If req failed due to problem with Channel. */
+       PL330_ERR_FAIL,
+};
+
+/* A request defining Scatter-Gather List ending with NULL xfer. */
+struct pl330_req {
+       enum pl330_reqtype rqtype;
+       /* Index of peripheral for the xfer. */
+       unsigned peri:5;
+       /* Unique token for this xfer, set by the client. */
+       void *token;
+       /* Callback to be called after xfer. */
+       void (*xfer_cb)(void *token, enum pl330_op_err err);
+       /* If NULL, req will be done at last set parameters. */
+       struct pl330_reqcfg *cfg;
+       /* Pointer to first xfer in the request. */
+       struct pl330_xfer *x;
+};
+
+/*
+ * To know the status of the channel and DMAC, the client
+ * provides a pointer to this structure. The PL330 core
+ * fills it with current information.
+ */
+struct pl330_chanstatus {
+       /*
+        * If the DMAC engine halted due to some error,
+        * the client should remove-add DMAC.
+        */
+       bool dmac_halted;
+       /*
+        * If channel is halted due to some error,
+        * the client should ABORT/FLUSH and START the channel.
+        */
+       bool faulting;
+       /* Location of last load */
+       u32 src_addr;
+       /* Location of last store */
+       u32 dst_addr;
+       /*
+        * Pointer to the currently active req, NULL if channel is
+        * inactive, even though the requests may be present.
+        */
+       struct pl330_req *top_req;
+       /* Pointer to req waiting second in the queue if any. */
+       struct pl330_req *wait_req;
+};
+
+enum pl330_chan_op {
+       /* Start the channel */
+       PL330_OP_START,
+       /* Abort the active xfer */
+       PL330_OP_ABORT,
+       /* Stop xfer and flush queue */
+       PL330_OP_FLUSH,
+};
+
+struct _xfer_spec {
+       u32 ccr;
+       struct pl330_req *r;
+       struct pl330_xfer *x;
+};
+
+enum dmamov_dst {
+       SAR = 0,
+       CCR,
+       DAR,
+};
+
+enum pl330_dst {
+       SRC = 0,
+       DST,
+};
+
+enum pl330_cond {
+       SINGLE,
+       BURST,
+       ALWAYS,
+};
+
+struct _pl330_req {
+       u32 mc_bus;
+       void *mc_cpu;
+       /* Number of bytes taken to setup MC for the req */
+       u32 mc_len;
+       struct pl330_req *r;
+       /* Hook to attach to DMAC's list of reqs with due callback */
+       struct list_head rqd;
+};
+
+/* ToBeDone for tasklet */
+struct _pl330_tbd {
+       bool reset_dmac;
+       bool reset_mngr;
+       u8 reset_chan;
+};
+
+/* A DMAC Thread */
+struct pl330_thread {
+       u8 id;
+       int ev;
+       /* If the channel is not yet acquired by any client */
+       bool free;
+       /* Parent DMAC */
+       struct pl330_dmac *dmac;
+       /* Only two at a time */
+       struct _pl330_req req[2];
+       /* Index of the last enqueued request */
+       unsigned lstenq;
+       /* Index of the last submitted request or -1 if the DMA is stopped */
+       int req_running;
+};
+
+enum pl330_dmac_state {
+       UNINIT,
+       INIT,
+       DYING,
+};
+
+/* A DMAC */
+struct pl330_dmac {
+       spinlock_t              lock;
+       /* Holds list of reqs with due callbacks */
+       struct list_head        req_done;
+       /* Pointer to platform specific stuff */
+       struct pl330_info       *pinfo;
+       /* Maximum possible events/irqs */
+       int                     events[32];
+       /* BUS address of MicroCode buffer */
+       u32                     mcode_bus;
+       /* CPU address of MicroCode buffer */
+       void                    *mcode_cpu;
+       /* List of all Channel threads */
+       struct pl330_thread     *channels;
+       /* Pointer to the MANAGER thread */
+       struct pl330_thread     *manager;
+       /* To handle bad news in interrupt */
+       struct tasklet_struct   tasks;
+       struct _pl330_tbd       dmac_tbd;
+       /* State of DMAC operation */
+       enum pl330_dmac_state   state;
+};
+
+enum desc_status {
+       /* In the DMAC pool */
+       FREE,
+       /*
+        * Allocted to some channel during prep_xxx
+        * Also may be sitting on the work_list.
+        */
+       PREP,
+       /*
+        * Sitting on the work_list and already submitted
+        * to the PL330 core. Not more than two descriptors
+        * of a channel can be BUSY at any time.
+        */
+       BUSY,
+       /*
+        * Sitting on the channel work_list but xfer done
+        * by PL330 core
+        */
+       DONE,
+};
+
+struct dma_pl330_chan {
+       /* Schedule desc completion */
+       struct tasklet_struct task;
+
+       /* DMA-Engine Channel */
+       struct dma_chan chan;
+
+       /* List of to be xfered descriptors */
+       struct list_head work_list;
+
+       /* Pointer to the DMAC that manages this channel,
+        * NULL if the channel is available to be acquired.
+        * As the parent, this DMAC also provides descriptors
+        * to the channel.
+        */
+       struct dma_pl330_dmac *dmac;
+
+       /* To protect channel manipulation */
+       spinlock_t lock;
+
+       /* Token of a hardware channel thread of PL330 DMAC
+        * NULL if the channel is available to be acquired.
+        */
+       void *pl330_chid;
+
+       /* For D-to-M and M-to-D channels */
+       int burst_sz; /* the peripheral fifo width */
+       int burst_len; /* the number of burst */
+       dma_addr_t fifo_addr;
+
+       /* for cyclic capability */
+       bool cyclic;
+};
+
+struct dma_pl330_dmac {
+       struct pl330_info pif;
+
+       /* DMA-Engine Device */
+       struct dma_device ddma;
+
+       /* Pool of descriptors available for the DMAC's channels */
+       struct list_head desc_pool;
+       /* To protect desc_pool manipulation */
+       spinlock_t pool_lock;
+
+       /* Peripheral channels connected to this DMAC */
+       struct dma_pl330_chan *peripherals; /* keep at end */
+
+       struct clk *clk;
+};
+
+struct dma_pl330_desc {
+       /* To attach to a queue as child */
+       struct list_head node;
+
+       /* Descriptor for the DMA Engine API */
+       struct dma_async_tx_descriptor txd;
+
+       /* Xfer for PL330 core */
+       struct pl330_xfer px;
+
+       struct pl330_reqcfg rqcfg;
+       struct pl330_req req;
+
+       enum desc_status status;
+
+       /* The channel which currently holds this desc */
+       struct dma_pl330_chan *pchan;
+};
+
+static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
+{
+       if (r && r->xfer_cb)
+               r->xfer_cb(r->token, err);
+}
+
+static inline bool _queue_empty(struct pl330_thread *thrd)
+{
+       return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
+               ? true : false;
+}
+
+static inline bool _queue_full(struct pl330_thread *thrd)
+{
+       return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
+               ? false : true;
+}
+
+static inline bool is_manager(struct pl330_thread *thrd)
+{
+       struct pl330_dmac *pl330 = thrd->dmac;
+
+       /* MANAGER is indexed at the end */
+       if (thrd->id == pl330->pinfo->pcfg.num_chan)
+               return true;
+       else
+               return false;
+}
+
+/* If manager of the thread is in Non-Secure mode */
+static inline bool _manager_ns(struct pl330_thread *thrd)
+{
+       struct pl330_dmac *pl330 = thrd->dmac;
+
+       return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
+}
+
+static inline u32 get_id(struct pl330_info *pi, u32 off)
+{
+       void __iomem *regs = pi->base;
+       u32 id = 0;
+
+       id |= (readb(regs + off + 0x0) << 0);
+       id |= (readb(regs + off + 0x4) << 8);
+       id |= (readb(regs + off + 0x8) << 16);
+       id |= (readb(regs + off + 0xc) << 24);
+
+       return id;
+}
+
+static inline u32 get_revision(u32 periph_id)
+{
+       return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
+}
+
+static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
+               enum pl330_dst da, u16 val)
+{
+       if (dry_run)
+               return SZ_DMAADDH;
+
+       buf[0] = CMD_DMAADDH;
+       buf[0] |= (da << 1);
+       *((u16 *)&buf[1]) = val;
+
+       PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
+               da == 1 ? "DA" : "SA", val);
+
+       return SZ_DMAADDH;
+}
+
+static inline u32 _emit_END(unsigned dry_run, u8 buf[])
+{
+       if (dry_run)
+               return SZ_DMAEND;
+
+       buf[0] = CMD_DMAEND;
+
+       PL330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n");
+
+       return SZ_DMAEND;
+}
+
+static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri)
+{
+       if (dry_run)
+               return SZ_DMAFLUSHP;
+
+       buf[0] = CMD_DMAFLUSHP;
+
+       peri &= 0x1f;
+       peri <<= 3;
+       buf[1] = peri;
+
+       PL330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3);
+
+       return SZ_DMAFLUSHP;
+}
+
+static inline u32 _emit_LD(unsigned dry_run, u8 buf[], enum pl330_cond cond)
+{
+       if (dry_run)
+               return SZ_DMALD;
+
+       buf[0] = CMD_DMALD;
+
+       if (cond == SINGLE)
+               buf[0] |= (0 << 1) | (1 << 0);
+       else if (cond == BURST)
+               buf[0] |= (1 << 1) | (1 << 0);
+
+       PL330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n",
+               cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
+
+       return SZ_DMALD;
+}
+
+static inline u32 _emit_LDP(unsigned dry_run, u8 buf[],
+               enum pl330_cond cond, u8 peri)
+{
+       if (dry_run)
+               return SZ_DMALDP;
+
+       buf[0] = CMD_DMALDP;
+
+       if (cond == BURST)
+               buf[0] |= (1 << 1);
+
+       peri &= 0x1f;
+       peri <<= 3;
+       buf[1] = peri;
+
+       PL330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n",
+               cond == SINGLE ? 'S' : 'B', peri >> 3);
+
+       return SZ_DMALDP;
+}
+
+static inline u32 _emit_LP(unsigned dry_run, u8 buf[],
+               unsigned loop, u8 cnt)
+{
+       if (dry_run)
+               return SZ_DMALP;
+
+       buf[0] = CMD_DMALP;
+
+       if (loop)
+               buf[0] |= (1 << 1);
+
+       cnt--; /* DMAC increments by 1 internally */
+       buf[1] = cnt;
+
+       PL330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt);
+
+       return SZ_DMALP;
+}
+
+struct _arg_LPEND {
+       enum pl330_cond cond;
+       bool forever;
+       unsigned loop;
+       u8 bjump;
+};
+
+static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[],
+               const struct _arg_LPEND *arg)
+{
+       enum pl330_cond cond = arg->cond;
+       bool forever = arg->forever;
+       unsigned loop = arg->loop;
+       u8 bjump = arg->bjump;
+
+       if (dry_run)
+               return SZ_DMALPEND;
+
+       buf[0] = CMD_DMALPEND;
+
+       if (loop)
+               buf[0] |= (1 << 2);
+
+       if (!forever)
+               buf[0] |= (1 << 4);
+
+       if (cond == SINGLE)
+               buf[0] |= (0 << 1) | (1 << 0);
+       else if (cond == BURST)
+               buf[0] |= (1 << 1) | (1 << 0);
+
+       buf[1] = bjump;
+
+       PL330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n",
+                       forever ? "FE" : "END",
+                       cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'),
+                       loop ? '1' : '0',
+                       bjump);
+
+       return SZ_DMALPEND;
+}
+
+static inline u32 _emit_KILL(unsigned dry_run, u8 buf[])
+{
+       if (dry_run)
+               return SZ_DMAKILL;
+
+       buf[0] = CMD_DMAKILL;
+
+       return SZ_DMAKILL;
+}
+
+static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
+               enum dmamov_dst dst, u32 val)
+{
+       if (dry_run)
+               return SZ_DMAMOV;
+
+       buf[0] = CMD_DMAMOV;
+       buf[1] = dst;
+       *((u32 *)&buf[2]) = val;
+
+       PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
+               dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
+
+       return SZ_DMAMOV;
+}
+
+static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
+{
+       if (dry_run)
+               return SZ_DMANOP;
+
+       buf[0] = CMD_DMANOP;
+
+       PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
+
+       return SZ_DMANOP;
+}
+
+static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
+{
+       if (dry_run)
+               return SZ_DMARMB;
+
+       buf[0] = CMD_DMARMB;
+
+       PL330_DBGCMD_DUMP(SZ_DMARMB, "\tDMARMB\n");
+
+       return SZ_DMARMB;
+}
+
+static inline u32 _emit_SEV(unsigned dry_run, u8 buf[], u8 ev)
+{
+       if (dry_run)
+               return SZ_DMASEV;
+
+       buf[0] = CMD_DMASEV;
+
+       ev &= 0x1f;
+       ev <<= 3;
+       buf[1] = ev;
+
+       PL330_DBGCMD_DUMP(SZ_DMASEV, "\tDMASEV %u\n", ev >> 3);
+
+       return SZ_DMASEV;
+}
+
+static inline u32 _emit_ST(unsigned dry_run, u8 buf[], enum pl330_cond cond)
+{
+       if (dry_run)
+               return SZ_DMAST;
+
+       buf[0] = CMD_DMAST;
+
+       if (cond == SINGLE)
+               buf[0] |= (0 << 1) | (1 << 0);
+       else if (cond == BURST)
+               buf[0] |= (1 << 1) | (1 << 0);
+
+       PL330_DBGCMD_DUMP(SZ_DMAST, "\tDMAST%c\n",
+               cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
+
+       return SZ_DMAST;
+}
+
+static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
+               enum pl330_cond cond, u8 peri)
+{
+       if (dry_run)
+               return SZ_DMASTP;
+
+       buf[0] = CMD_DMASTP;
+
+       if (cond == BURST)
+               buf[0] |= (1 << 1);
+
+       peri &= 0x1f;
+       peri <<= 3;
+       buf[1] = peri;
+
+       PL330_DBGCMD_DUMP(SZ_DMASTP, "\tDMASTP%c %u\n",
+               cond == SINGLE ? 'S' : 'B', peri >> 3);
+
+       return SZ_DMASTP;
+}
+
+static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
+{
+       if (dry_run)
+               return SZ_DMASTZ;
+
+       buf[0] = CMD_DMASTZ;
+
+       PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
+
+       return SZ_DMASTZ;
+}
+
+static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
+               unsigned invalidate)
+{
+       if (dry_run)
+               return SZ_DMAWFE;
+
+       buf[0] = CMD_DMAWFE;
+
+       ev &= 0x1f;
+       ev <<= 3;
+       buf[1] = ev;
+
+       if (invalidate)
+               buf[1] |= (1 << 1);
+
+       PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
+               ev >> 3, invalidate ? ", I" : "");
+
+       return SZ_DMAWFE;
+}
+
+static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
+               enum pl330_cond cond, u8 peri)
+{
+       if (dry_run)
+               return SZ_DMAWFP;
+
+       buf[0] = CMD_DMAWFP;
+
+       if (cond == SINGLE)
+               buf[0] |= (0 << 1) | (0 << 0);
+       else if (cond == BURST)
+               buf[0] |= (1 << 1) | (0 << 0);
+       else
+               buf[0] |= (0 << 1) | (1 << 0);
+
+       peri &= 0x1f;
+       peri <<= 3;
+       buf[1] = peri;
+
+       PL330_DBGCMD_DUMP(SZ_DMAWFP, "\tDMAWFP%c %u\n",
+               cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'P'), peri >> 3);
+
+       return SZ_DMAWFP;
+}
+
+static inline u32 _emit_WMB(unsigned dry_run, u8 buf[])
+{
+       if (dry_run)
+               return SZ_DMAWMB;
+
+       buf[0] = CMD_DMAWMB;
+
+       PL330_DBGCMD_DUMP(SZ_DMAWMB, "\tDMAWMB\n");
+
+       return SZ_DMAWMB;
+}
+
+struct _arg_GO {
+       u8 chan;
+       u32 addr;
+       unsigned ns;
+};
+
+static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
+               const struct _arg_GO *arg)
+{
+       u8 chan = arg->chan;
+       u32 addr = arg->addr;
+       unsigned ns = arg->ns;
+
+       if (dry_run)
+               return SZ_DMAGO;
+
+       buf[0] = CMD_DMAGO;
+       buf[0] |= (ns << 1);
+
+       buf[1] = chan & 0x7;
+
+       *((u32 *)&buf[2]) = addr;
+
+       return SZ_DMAGO;
+}
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+/* Returns Time-Out */
+static bool _until_dmac_idle(struct pl330_thread *thrd)
+{
+       void __iomem *regs = thrd->dmac->pinfo->base;
+       unsigned long loops = msecs_to_loops(5);
+
+       do {
+               /* Until Manager is Idle */
+               if (!(readl(regs + DBGSTATUS) & DBG_BUSY))
+                       break;
+
+               cpu_relax();
+       } while (--loops);
+
+       if (!loops)
+               return true;
+
+       return false;
+}
+
+static inline void _execute_DBGINSN(struct pl330_thread *thrd,
+               u8 insn[], bool as_manager)
+{
+       void __iomem *regs = thrd->dmac->pinfo->base;
+       u32 val;
+
+       val = (insn[0] << 16) | (insn[1] << 24);
+       if (!as_manager) {
+               val |= (1 << 0);
+               val |= (thrd->id << 8); /* Channel Number */
+       }
+       writel(val, regs + DBGINST0);
+
+       val = *((u32 *)&insn[2]);
+       writel(val, regs + DBGINST1);
+
+       /* If timed out due to halted state-machine */
+       if (_until_dmac_idle(thrd)) {
+               dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n");
+               return;
+       }
+
+       /* Get going */
+       writel(0, regs + DBGCMD);
+}
+
+/*
+ * Mark a _pl330_req as free.
+ * We do it by writing DMAEND as the first instruction
+ * because no valid request is going to have DMAEND as
+ * its first instruction to execute.
+ */
+static void mark_free(struct pl330_thread *thrd, int idx)
+{
+       struct _pl330_req *req = &thrd->req[idx];
+
+       _emit_END(0, req->mc_cpu);
+       req->mc_len = 0;
+
+       thrd->req_running = -1;
+}
+
+static inline u32 _state(struct pl330_thread *thrd)
+{
+       void __iomem *regs = thrd->dmac->pinfo->base;
+       u32 val;
+
+       if (is_manager(thrd))
+               val = readl(regs + DS) & 0xf;
+       else
+               val = readl(regs + CS(thrd->id)) & 0xf;
+
+       switch (val) {
+       case DS_ST_STOP:
+               return PL330_STATE_STOPPED;
+       case DS_ST_EXEC:
+               return PL330_STATE_EXECUTING;
+       case DS_ST_CMISS:
+               return PL330_STATE_CACHEMISS;
+       case DS_ST_UPDTPC:
+               return PL330_STATE_UPDTPC;
+       case DS_ST_WFE:
+               return PL330_STATE_WFE;
+       case DS_ST_FAULT:
+               return PL330_STATE_FAULTING;
+       case DS_ST_ATBRR:
+               if (is_manager(thrd))
+                       return PL330_STATE_INVALID;
+               else
+                       return PL330_STATE_ATBARRIER;
+       case DS_ST_QBUSY:
+               if (is_manager(thrd))
+                       return PL330_STATE_INVALID;
+               else
+                       return PL330_STATE_QUEUEBUSY;
+       case DS_ST_WFP:
+               if (is_manager(thrd))
+                       return PL330_STATE_INVALID;
+               else
+                       return PL330_STATE_WFP;
+       case DS_ST_KILL:
+               if (is_manager(thrd))
+                       return PL330_STATE_INVALID;
+               else
+                       return PL330_STATE_KILLING;
+       case DS_ST_CMPLT:
+               if (is_manager(thrd))
+                       return PL330_STATE_INVALID;
+               else
+                       return PL330_STATE_COMPLETING;
+       case DS_ST_FLTCMP:
+               if (is_manager(thrd))
+                       return PL330_STATE_INVALID;
+               else
+                       return PL330_STATE_FAULT_COMPLETING;
+       default:
+               return PL330_STATE_INVALID;
+       }
+}
+
+static void _stop(struct pl330_thread *thrd)
+{
+       void __iomem *regs = thrd->dmac->pinfo->base;
+       u8 insn[6] = {0, 0, 0, 0, 0, 0};
+
+       if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
+               UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
+
+       /* Return if nothing needs to be done */
+       if (_state(thrd) == PL330_STATE_COMPLETING
+                 || _state(thrd) == PL330_STATE_KILLING
+                 || _state(thrd) == PL330_STATE_STOPPED)
+               return;
+
+       _emit_KILL(0, insn);
+
+       /* Stop generating interrupts for SEV */
+       writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
+
+       _execute_DBGINSN(thrd, insn, is_manager(thrd));
+}
+
+/* Start doing req 'idx' of thread 'thrd' */
+static bool _trigger(struct pl330_thread *thrd)
+{
+       void __iomem *regs = thrd->dmac->pinfo->base;
+       struct _pl330_req *req;
+       struct pl330_req *r;
+       struct _arg_GO go;
+       unsigned ns;
+       u8 insn[6] = {0, 0, 0, 0, 0, 0};
+       int idx;
+
+       /* Return if already ACTIVE */
+       if (_state(thrd) != PL330_STATE_STOPPED)
+               return true;
+
+       idx = 1 - thrd->lstenq;
+       if (!IS_FREE(&thrd->req[idx]))
+               req = &thrd->req[idx];
+       else {
+               idx = thrd->lstenq;
+               if (!IS_FREE(&thrd->req[idx]))
+                       req = &thrd->req[idx];
+               else
+                       req = NULL;
+       }
+
+       /* Return if no request */
+       if (!req || !req->r)
+               return true;
+
+       r = req->r;
+
+       if (r->cfg)
+               ns = r->cfg->nonsecure ? 1 : 0;
+       else if (readl(regs + CS(thrd->id)) & CS_CNS)
+               ns = 1;
+       else
+               ns = 0;
+
+       /* See 'Abort Sources' point-4 at Page 2-25 */
+       if (_manager_ns(thrd) && !ns)
+               dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n",
+                       __func__, __LINE__);
+
+       go.chan = thrd->id;
+       go.addr = req->mc_bus;
+       go.ns = ns;
+       _emit_GO(0, insn, &go);
+
+       /* Set to generate interrupts for SEV */
+       writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN);
+
+       /* Only manager can execute GO */
+       _execute_DBGINSN(thrd, insn, true);
+
+       thrd->req_running = idx;
+
+       return true;
+}
+
+static bool _start(struct pl330_thread *thrd)
+{
+       switch (_state(thrd)) {
+       case PL330_STATE_FAULT_COMPLETING:
+               UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
+
+               if (_state(thrd) == PL330_STATE_KILLING)
+                       UNTIL(thrd, PL330_STATE_STOPPED)
+
+       case PL330_STATE_FAULTING:
+               _stop(thrd);
+
+       case PL330_STATE_KILLING:
+       case PL330_STATE_COMPLETING:
+               UNTIL(thrd, PL330_STATE_STOPPED)
+
+       case PL330_STATE_STOPPED:
+               return _trigger(thrd);
+
+       case PL330_STATE_WFP:
+       case PL330_STATE_QUEUEBUSY:
+       case PL330_STATE_ATBARRIER:
+       case PL330_STATE_UPDTPC:
+       case PL330_STATE_CACHEMISS:
+       case PL330_STATE_EXECUTING:
+               return true;
+
+       case PL330_STATE_WFE: /* For RESUME, nothing yet */
+       default:
+               return false;
+       }
+}
+
+static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
+               const struct _xfer_spec *pxs, int cyc)
+{
+       int off = 0;
+       struct pl330_config *pcfg = pxs->r->cfg->pcfg;
+
+       /* check lock-up free version */
+       if (get_revision(pcfg->periph_id) >= PERIPH_REV_R1P0) {
+               while (cyc--) {
+                       off += _emit_LD(dry_run, &buf[off], ALWAYS);
+                       off += _emit_ST(dry_run, &buf[off], ALWAYS);
+               }
+       } else {
+               while (cyc--) {
+                       off += _emit_LD(dry_run, &buf[off], ALWAYS);
+                       off += _emit_RMB(dry_run, &buf[off]);
+                       off += _emit_ST(dry_run, &buf[off], ALWAYS);
+                       off += _emit_WMB(dry_run, &buf[off]);
+               }
+       }
+
+       return off;
+}
+
+static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
+               const struct _xfer_spec *pxs, int cyc)
+{
+       int off = 0;
+
+       while (cyc--) {
+               off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+               off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+               off += _emit_ST(dry_run, &buf[off], ALWAYS);
+               off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+       }
+
+       return off;
+}
+
+static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
+               const struct _xfer_spec *pxs, int cyc)
+{
+       int off = 0;
+
+       while (cyc--) {
+               off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+               off += _emit_LD(dry_run, &buf[off], ALWAYS);
+               off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+               off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+       }
+
+       return off;
+}
+
+static int _bursts(unsigned dry_run, u8 buf[],
+               const struct _xfer_spec *pxs, int cyc)
+{
+       int off = 0;
+
+       switch (pxs->r->rqtype) {
+       case MEMTODEV:
+               off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
+               break;
+       case DEVTOMEM:
+               off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
+               break;
+       case MEMTOMEM:
+               off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
+               break;
+       default:
+               off += 0x40000000; /* Scare off the Client */
+               break;
+       }
+
+       return off;
+}
+
+/* Returns bytes consumed and updates bursts */
+static inline int _loop(unsigned dry_run, u8 buf[],
+               unsigned long *bursts, const struct _xfer_spec *pxs)
+{
+       int cyc, cycmax, szlp, szlpend, szbrst, off;
+       unsigned lcnt0, lcnt1, ljmp0, ljmp1;
+       struct _arg_LPEND lpend;
+
+       /* Max iterations possible in DMALP is 256 */
+       if (*bursts >= 256*256) {
+               lcnt1 = 256;
+               lcnt0 = 256;
+               cyc = *bursts / lcnt1 / lcnt0;
+       } else if (*bursts > 256) {
+               lcnt1 = 256;
+               lcnt0 = *bursts / lcnt1;
+               cyc = 1;
+       } else {
+               lcnt1 = *bursts;
+               lcnt0 = 0;
+               cyc = 1;
+       }
+
+       szlp = _emit_LP(1, buf, 0, 0);
+       szbrst = _bursts(1, buf, pxs, 1);
+
+       lpend.cond = ALWAYS;
+       lpend.forever = false;
+       lpend.loop = 0;
+       lpend.bjump = 0;
+       szlpend = _emit_LPEND(1, buf, &lpend);
+
+       if (lcnt0) {
+               szlp *= 2;
+               szlpend *= 2;
+       }
+
+       /*
+        * Max bursts that we can unroll due to limit on the
+        * size of backward jump that can be encoded in DMALPEND
+        * which is 8-bits and hence 255
+        */
+       cycmax = (255 - (szlp + szlpend)) / szbrst;
+
+       cyc = (cycmax < cyc) ? cycmax : cyc;
+
+       off = 0;
+
+       if (lcnt0) {
+               off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
+               ljmp0 = off;
+       }
+
+       off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
+       ljmp1 = off;
+
+       off += _bursts(dry_run, &buf[off], pxs, cyc);
+
+       lpend.cond = ALWAYS;
+       lpend.forever = false;
+       lpend.loop = 1;
+       lpend.bjump = off - ljmp1;
+       off += _emit_LPEND(dry_run, &buf[off], &lpend);
+
+       if (lcnt0) {
+               lpend.cond = ALWAYS;
+               lpend.forever = false;
+               lpend.loop = 0;
+               lpend.bjump = off - ljmp0;
+               off += _emit_LPEND(dry_run, &buf[off], &lpend);
+       }
+
+       *bursts = lcnt1 * cyc;
+       if (lcnt0)
+               *bursts *= lcnt0;
+
+       return off;
+}
+
+static inline int _setup_loops(unsigned dry_run, u8 buf[],
+               const struct _xfer_spec *pxs)
+{
+       struct pl330_xfer *x = pxs->x;
+       u32 ccr = pxs->ccr;
+       unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
+       int off = 0;
+
+       while (bursts) {
+               c = bursts;
+               off += _loop(dry_run, &buf[off], &c, pxs);
+               bursts -= c;
+       }
+
+       return off;
+}
+
+static inline int _setup_xfer(unsigned dry_run, u8 buf[],
+               const struct _xfer_spec *pxs)
+{
+       struct pl330_xfer *x = pxs->x;
+       int off = 0;
+
+       /* DMAMOV SAR, x->src_addr */
+       off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
+       /* DMAMOV DAR, x->dst_addr */
+       off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
+
+       /* Setup Loop(s) */
+       off += _setup_loops(dry_run, &buf[off], pxs);
+
+       return off;
+}
+
+/*
+ * A req is a sequence of one or more xfer units.
+ * Returns the number of bytes taken to setup the MC for the req.
+ */
+static int _setup_req(unsigned dry_run, struct pl330_thread *thrd,
+               unsigned index, struct _xfer_spec *pxs)
+{
+       struct _pl330_req *req = &thrd->req[index];
+       struct pl330_xfer *x;
+       u8 *buf = req->mc_cpu;
+       int off = 0;
+
+       PL330_DBGMC_START(req->mc_bus);
+
+       /* DMAMOV CCR, ccr */
+       off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
+
+       x = pxs->r->x;
+       do {
+               /* Error if xfer length is not aligned at burst size */
+               if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
+                       return -EINVAL;
+
+               pxs->x = x;
+               off += _setup_xfer(dry_run, &buf[off], pxs);
+
+               x = x->next;
+       } while (x);
+
+       /* DMASEV peripheral/event */
+       off += _emit_SEV(dry_run, &buf[off], thrd->ev);
+       /* DMAEND */
+       off += _emit_END(dry_run, &buf[off]);
+
+       return off;
+}
+
+static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
+{
+       u32 ccr = 0;
+
+       if (rqc->src_inc)
+               ccr |= CC_SRCINC;
+
+       if (rqc->dst_inc)
+               ccr |= CC_DSTINC;
+
+       /* We set same protection levels for Src and DST for now */
+       if (rqc->privileged)
+               ccr |= CC_SRCPRI | CC_DSTPRI;
+       if (rqc->nonsecure)
+               ccr |= CC_SRCNS | CC_DSTNS;
+       if (rqc->insnaccess)
+               ccr |= CC_SRCIA | CC_DSTIA;
+
+       ccr |= (((rqc->brst_len - 1) & 0xf) << CC_SRCBRSTLEN_SHFT);
+       ccr |= (((rqc->brst_len - 1) & 0xf) << CC_DSTBRSTLEN_SHFT);
+
+       ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
+       ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
+
+       ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
+       ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
+
+       ccr |= (rqc->swap << CC_SWAP_SHFT);
+
+       return ccr;
+}
+
+static inline bool _is_valid(u32 ccr)
+{
+       enum pl330_dstcachectrl dcctl;
+       enum pl330_srccachectrl scctl;
+
+       dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK;
+       scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK;
+
+       if (dcctl == DINVALID1 || dcctl == DINVALID2
+                       || scctl == SINVALID1 || scctl == SINVALID2)
+               return false;
+       else
+               return true;
+}
+
+/*
+ * Submit a list of xfers after which the client wants notification.
+ * Client is not notified after each xfer unit, just once after all
+ * xfer units are done or some error occurs.
+ */
+static int pl330_submit_req(void *ch_id, struct pl330_req *r)
+{
+       struct pl330_thread *thrd = ch_id;
+       struct pl330_dmac *pl330;
+       struct pl330_info *pi;
+       struct _xfer_spec xs;
+       unsigned long flags;
+       void __iomem *regs;
+       unsigned idx;
+       u32 ccr;
+       int ret = 0;
+
+       /* No Req or Unacquired Channel or DMAC */
+       if (!r || !thrd || thrd->free)
+               return -EINVAL;
+
+       pl330 = thrd->dmac;
+       pi = pl330->pinfo;
+       regs = pi->base;
+
+       if (pl330->state == DYING
+               || pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
+               dev_info(thrd->dmac->pinfo->dev, "%s:%d\n",
+                       __func__, __LINE__);
+               return -EAGAIN;
+       }
+
+       /* If request for non-existing peripheral */
+       if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) {
+               dev_info(thrd->dmac->pinfo->dev,
+                               "%s:%d Invalid peripheral(%u)!\n",
+                               __func__, __LINE__, r->peri);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&pl330->lock, flags);
+
+       if (_queue_full(thrd)) {
+               ret = -EAGAIN;
+               goto xfer_exit;
+       }
+
+       /* Prefer Secure Channel */
+       if (!_manager_ns(thrd))
+               r->cfg->nonsecure = 0;
+       else
+               r->cfg->nonsecure = 1;
+
+       /* Use last settings, if not provided */
+       if (r->cfg)
+               ccr = _prepare_ccr(r->cfg);
+       else
+               ccr = readl(regs + CC(thrd->id));
+
+       /* If this req doesn't have valid xfer settings */
+       if (!_is_valid(ccr)) {
+               ret = -EINVAL;
+               dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n",
+                       __func__, __LINE__, ccr);
+               goto xfer_exit;
+       }
+
+       idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
+
+       xs.ccr = ccr;
+       xs.r = r;
+
+       /* First dry run to check if req is acceptable */
+       ret = _setup_req(1, thrd, idx, &xs);
+       if (ret < 0)
+               goto xfer_exit;
+
+       if (ret > pi->mcbufsz / 2) {
+               dev_info(thrd->dmac->pinfo->dev,
+                       "%s:%d Trying increasing mcbufsz\n",
+                               __func__, __LINE__);
+               ret = -ENOMEM;
+               goto xfer_exit;
+       }
+
+       /* Hook the request */
+       thrd->lstenq = idx;
+       thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs);
+       thrd->req[idx].r = r;
+
+       ret = 0;
+
+xfer_exit:
+       spin_unlock_irqrestore(&pl330->lock, flags);
+
+       return ret;
+}
+
+static void pl330_dotask(unsigned long data)
+{
+       struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
+       struct pl330_info *pi = pl330->pinfo;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&pl330->lock, flags);
+
+       /* The DMAC itself gone nuts */
+       if (pl330->dmac_tbd.reset_dmac) {
+               pl330->state = DYING;
+               /* Reset the manager too */
+               pl330->dmac_tbd.reset_mngr = true;
+               /* Clear the reset flag */
+               pl330->dmac_tbd.reset_dmac = false;
+       }
+
+       if (pl330->dmac_tbd.reset_mngr) {
+               _stop(pl330->manager);
+               /* Reset all channels */
+               pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1;
+               /* Clear the reset flag */
+               pl330->dmac_tbd.reset_mngr = false;
+       }
+
+       for (i = 0; i < pi->pcfg.num_chan; i++) {
+
+               if (pl330->dmac_tbd.reset_chan & (1 << i)) {
+                       struct pl330_thread *thrd = &pl330->channels[i];
+                       void __iomem *regs = pi->base;
+                       enum pl330_op_err err;
+
+                       _stop(thrd);
+
+                       if (readl(regs + FSC) & (1 << thrd->id))
+                               err = PL330_ERR_FAIL;
+                       else
+                               err = PL330_ERR_ABORT;
+
+                       spin_unlock_irqrestore(&pl330->lock, flags);
+
+                       _callback(thrd->req[1 - thrd->lstenq].r, err);
+                       _callback(thrd->req[thrd->lstenq].r, err);
+
+                       spin_lock_irqsave(&pl330->lock, flags);
+
+                       thrd->req[0].r = NULL;
+                       thrd->req[1].r = NULL;
+                       mark_free(thrd, 0);
+                       mark_free(thrd, 1);
+
+                       /* Clear the reset flag */
+                       pl330->dmac_tbd.reset_chan &= ~(1 << i);
+               }
+       }
+
+       spin_unlock_irqrestore(&pl330->lock, flags);
+
+       return;
+}
+
+/* Returns 1 if state was updated, 0 otherwise */
+static int pl330_update(const struct pl330_info *pi)
+{
+       struct _pl330_req *rqdone;
+       struct pl330_dmac *pl330;
+       unsigned long flags;
+       void __iomem *regs;
+       u32 val;
+       int id, ev, ret = 0;
+
+       if (!pi || !pi->pl330_data)
+               return 0;
+
+       regs = pi->base;
+       pl330 = pi->pl330_data;
+
+       spin_lock_irqsave(&pl330->lock, flags);
+
+       val = readl(regs + FSM) & 0x1;
+       if (val)
+               pl330->dmac_tbd.reset_mngr = true;
+       else
+               pl330->dmac_tbd.reset_mngr = false;
+
+       val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
+       pl330->dmac_tbd.reset_chan |= val;
+       if (val) {
+               int i = 0;
+               while (i < pi->pcfg.num_chan) {
+                       if (val & (1 << i)) {
+                               dev_info(pi->dev,
+                                       "Reset Channel-%d\t CS-%x FTC-%x\n",
+                                               i, readl(regs + CS(i)),
+                                               readl(regs + FTC(i)));
+                               _stop(&pl330->channels[i]);
+                       }
+                       i++;
+               }
+       }
+
+       /* Check which event happened i.e, thread notified */
+       val = readl(regs + ES);
+       if (pi->pcfg.num_events < 32
+                       && val & ~((1 << pi->pcfg.num_events) - 1)) {
+               pl330->dmac_tbd.reset_dmac = true;
+               dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__);
+               ret = 1;
+               goto updt_exit;
+       }
+
+       for (ev = 0; ev < pi->pcfg.num_events; ev++) {
+               if (val & (1 << ev)) { /* Event occurred */
+                       struct pl330_thread *thrd;
+                       u32 inten = readl(regs + INTEN);
+                       int active;
+
+                       /* Clear the event */
+                       if (inten & (1 << ev))
+                               writel(1 << ev, regs + INTCLR);
+
+                       ret = 1;
+
+                       id = pl330->events[ev];
+
+                       thrd = &pl330->channels[id];
+
+                       active = thrd->req_running;
+                       if (active == -1) /* Aborted */
+                               continue;
+
+                       rqdone = &thrd->req[active];
+                       mark_free(thrd, active);
+
+                       /* Get going again ASAP */
+                       _start(thrd);
+
+                       /* For now, just make a list of callbacks to be done */
+                       list_add_tail(&rqdone->rqd, &pl330->req_done);
+               }
+       }
+
+       /* Now that we are in no hurry, do the callbacks */
+       while (!list_empty(&pl330->req_done)) {
+               struct pl330_req *r;
+
+               rqdone = container_of(pl330->req_done.next,
+                                       struct _pl330_req, rqd);
+
+               list_del_init(&rqdone->rqd);
+
+               /* Detach the req */
+               r = rqdone->r;
+               rqdone->r = NULL;
+
+               spin_unlock_irqrestore(&pl330->lock, flags);
+               _callback(r, PL330_ERR_NONE);
+               spin_lock_irqsave(&pl330->lock, flags);
+       }
+
+updt_exit:
+       spin_unlock_irqrestore(&pl330->lock, flags);
+
+       if (pl330->dmac_tbd.reset_dmac
+                       || pl330->dmac_tbd.reset_mngr
+                       || pl330->dmac_tbd.reset_chan) {
+               ret = 1;
+               tasklet_schedule(&pl330->tasks);
+       }
+
+       return ret;
+}
+
+static int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
+{
+       struct pl330_thread *thrd = ch_id;
+       struct pl330_dmac *pl330;
+       unsigned long flags;
+       int ret = 0, active;
+
+       if (!thrd || thrd->free || thrd->dmac->state == DYING)
+               return -EINVAL;
+
+       pl330 = thrd->dmac;
+       active = thrd->req_running;
+
+       spin_lock_irqsave(&pl330->lock, flags);
+
+       switch (op) {
+       case PL330_OP_FLUSH:
+               /* Make sure the channel is stopped */
+               _stop(thrd);
+
+               thrd->req[0].r = NULL;
+               thrd->req[1].r = NULL;
+               mark_free(thrd, 0);
+               mark_free(thrd, 1);
+               break;
+
+       case PL330_OP_ABORT:
+               /* Make sure the channel is stopped */
+               _stop(thrd);
+
+               /* ABORT is only for the active req */
+               if (active == -1)
+                       break;
+
+               thrd->req[active].r = NULL;
+               mark_free(thrd, active);
+
+               /* Start the next */
+       case PL330_OP_START:
+               if ((active == -1) && !_start(thrd))
+                       ret = -EIO;
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       spin_unlock_irqrestore(&pl330->lock, flags);
+       return ret;
+}
+
+/* Reserve an event */
+static inline int _alloc_event(struct pl330_thread *thrd)
+{
+       struct pl330_dmac *pl330 = thrd->dmac;
+       struct pl330_info *pi = pl330->pinfo;
+       int ev;
+
+       for (ev = 0; ev < pi->pcfg.num_events; ev++)
+               if (pl330->events[ev] == -1) {
+                       pl330->events[ev] = thrd->id;
+                       return ev;
+               }
+
+       return -1;
+}
+
+static bool _chan_ns(const struct pl330_info *pi, int i)
+{
+       return pi->pcfg.irq_ns & (1 << i);
+}
+
+/* Upon success, returns IdentityToken for the
+ * allocated channel, NULL otherwise.
+ */
+static void *pl330_request_channel(const struct pl330_info *pi)
+{
+       struct pl330_thread *thrd = NULL;
+       struct pl330_dmac *pl330;
+       unsigned long flags;
+       int chans, i;
+
+       if (!pi || !pi->pl330_data)
+               return NULL;
 
-#define NR_DEFAULT_DESC        16
+       pl330 = pi->pl330_data;
+
+       if (pl330->state == DYING)
+               return NULL;
+
+       chans = pi->pcfg.num_chan;
+
+       spin_lock_irqsave(&pl330->lock, flags);
+
+       for (i = 0; i < chans; i++) {
+               thrd = &pl330->channels[i];
+               if ((thrd->free) && (!_manager_ns(thrd) ||
+                                       _chan_ns(pi, i))) {
+                       thrd->ev = _alloc_event(thrd);
+                       if (thrd->ev >= 0) {
+                               thrd->free = false;
+                               thrd->lstenq = 1;
+                               thrd->req[0].r = NULL;
+                               mark_free(thrd, 0);
+                               thrd->req[1].r = NULL;
+                               mark_free(thrd, 1);
+                               break;
+                       }
+               }
+               thrd = NULL;
+       }
+
+       spin_unlock_irqrestore(&pl330->lock, flags);
+
+       return thrd;
+}
+
+/* Release an event */
+static inline void _free_event(struct pl330_thread *thrd, int ev)
+{
+       struct pl330_dmac *pl330 = thrd->dmac;
+       struct pl330_info *pi = pl330->pinfo;
+
+       /* If the event is valid and was held by the thread */
+       if (ev >= 0 && ev < pi->pcfg.num_events
+                       && pl330->events[ev] == thrd->id)
+               pl330->events[ev] = -1;
+}
+
+static void pl330_release_channel(void *ch_id)
+{
+       struct pl330_thread *thrd = ch_id;
+       struct pl330_dmac *pl330;
+       unsigned long flags;
+
+       if (!thrd || thrd->free)
+               return;
+
+       _stop(thrd);
+
+       _callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT);
+       _callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT);
+
+       pl330 = thrd->dmac;
+
+       spin_lock_irqsave(&pl330->lock, flags);
+       _free_event(thrd, thrd->ev);
+       thrd->free = true;
+       spin_unlock_irqrestore(&pl330->lock, flags);
+}
+
+/* Initialize the structure for PL330 configuration, that can be used
+ * by the client driver the make best use of the DMAC
+ */
+static void read_dmac_config(struct pl330_info *pi)
+{
+       void __iomem *regs = pi->base;
+       u32 val;
+
+       val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
+       val &= CRD_DATA_WIDTH_MASK;
+       pi->pcfg.data_bus_width = 8 * (1 << val);
+
+       val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
+       val &= CRD_DATA_BUFF_MASK;
+       pi->pcfg.data_buf_dep = val + 1;
+
+       val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
+       val &= CR0_NUM_CHANS_MASK;
+       val += 1;
+       pi->pcfg.num_chan = val;
+
+       val = readl(regs + CR0);
+       if (val & CR0_PERIPH_REQ_SET) {
+               val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
+               val += 1;
+               pi->pcfg.num_peri = val;
+               pi->pcfg.peri_ns = readl(regs + CR4);
+       } else {
+               pi->pcfg.num_peri = 0;
+       }
+
+       val = readl(regs + CR0);
+       if (val & CR0_BOOT_MAN_NS)
+               pi->pcfg.mode |= DMAC_MODE_NS;
+       else
+               pi->pcfg.mode &= ~DMAC_MODE_NS;
+
+       val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
+       val &= CR0_NUM_EVENTS_MASK;
+       val += 1;
+       pi->pcfg.num_events = val;
+
+       pi->pcfg.irq_ns = readl(regs + CR3);
+
+       pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
+       pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
+}
+
+static inline void _reset_thread(struct pl330_thread *thrd)
+{
+       struct pl330_dmac *pl330 = thrd->dmac;
+       struct pl330_info *pi = pl330->pinfo;
+
+       thrd->req[0].mc_cpu = pl330->mcode_cpu
+                               + (thrd->id * pi->mcbufsz);
+       thrd->req[0].mc_bus = pl330->mcode_bus
+                               + (thrd->id * pi->mcbufsz);
+       thrd->req[0].r = NULL;
+       mark_free(thrd, 0);
+
+       thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
+                               + pi->mcbufsz / 2;
+       thrd->req[1].mc_bus = thrd->req[0].mc_bus
+                               + pi->mcbufsz / 2;
+       thrd->req[1].r = NULL;
+       mark_free(thrd, 1);
+}
+
+static int dmac_alloc_threads(struct pl330_dmac *pl330)
+{
+       struct pl330_info *pi = pl330->pinfo;
+       int chans = pi->pcfg.num_chan;
+       struct pl330_thread *thrd;
+       int i;
+
+       /* Allocate 1 Manager and 'chans' Channel threads */
+       pl330->channels = kzalloc((1 + chans) * sizeof(*thrd),
+                                       GFP_KERNEL);
+       if (!pl330->channels)
+               return -ENOMEM;
+
+       /* Init Channel threads */
+       for (i = 0; i < chans; i++) {
+               thrd = &pl330->channels[i];
+               thrd->id = i;
+               thrd->dmac = pl330;
+               _reset_thread(thrd);
+               thrd->free = true;
+       }
+
+       /* MANAGER is indexed at the end */
+       thrd = &pl330->channels[chans];
+       thrd->id = chans;
+       thrd->dmac = pl330;
+       thrd->free = false;
+       pl330->manager = thrd;
+
+       return 0;
+}
+
+static int dmac_alloc_resources(struct pl330_dmac *pl330)
+{
+       struct pl330_info *pi = pl330->pinfo;
+       int chans = pi->pcfg.num_chan;
+       int ret;
 
-enum desc_status {
-       /* In the DMAC pool */
-       FREE,
-       /*
-        * Allocted to some channel during prep_xxx
-        * Also may be sitting on the work_list.
-        */
-       PREP,
        /*
-        * Sitting on the work_list and already submitted
-        * to the PL330 core. Not more than two descriptors
-        * of a channel can be BUSY at any time.
+        * Alloc MicroCode buffer for 'chans' Channel threads.
+        * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN)
         */
-       BUSY,
+       pl330->mcode_cpu = dma_alloc_coherent(pi->dev,
+                               chans * pi->mcbufsz,
+                               &pl330->mcode_bus, GFP_KERNEL);
+       if (!pl330->mcode_cpu) {
+               dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
+                       __func__, __LINE__);
+               return -ENOMEM;
+       }
+
+       ret = dmac_alloc_threads(pl330);
+       if (ret) {
+               dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n",
+                       __func__, __LINE__);
+               dma_free_coherent(pi->dev,
+                               chans * pi->mcbufsz,
+                               pl330->mcode_cpu, pl330->mcode_bus);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int pl330_add(struct pl330_info *pi)
+{
+       struct pl330_dmac *pl330;
+       void __iomem *regs;
+       int i, ret;
+
+       if (!pi || !pi->dev)
+               return -EINVAL;
+
+       /* If already added */
+       if (pi->pl330_data)
+               return -EINVAL;
+
        /*
-        * Sitting on the channel work_list but xfer done
-        * by PL330 core
+        * If the SoC can perform reset on the DMAC, then do it
+        * before reading its configuration.
         */
-       DONE,
-};
+       if (pi->dmac_reset)
+               pi->dmac_reset(pi);
 
-struct dma_pl330_chan {
-       /* Schedule desc completion */
-       struct tasklet_struct task;
+       regs = pi->base;
 
-       /* DMA-Engine Channel */
-       struct dma_chan chan;
+       /* Check if we can handle this DMAC */
+       if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
+          || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
+               dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
+                       get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
+               return -EINVAL;
+       }
 
-       /* Last completed cookie */
-       dma_cookie_t completed;
+       /* Read the configuration of the DMAC */
+       read_dmac_config(pi);
 
-       /* List of to be xfered descriptors */
-       struct list_head work_list;
+       if (pi->pcfg.num_events == 0) {
+               dev_err(pi->dev, "%s:%d Can't work without events!\n",
+                       __func__, __LINE__);
+               return -EINVAL;
+       }
 
-       /* Pointer to the DMAC that manages this channel,
-        * NULL if the channel is available to be acquired.
-        * As the parent, this DMAC also provides descriptors
-        * to the channel.
-        */
-       struct dma_pl330_dmac *dmac;
+       pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL);
+       if (!pl330) {
+               dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
+                       __func__, __LINE__);
+               return -ENOMEM;
+       }
 
-       /* To protect channel manipulation */
-       spinlock_t lock;
+       /* Assign the info structure and private data */
+       pl330->pinfo = pi;
+       pi->pl330_data = pl330;
 
-       /* Token of a hardware channel thread of PL330 DMAC
-        * NULL if the channel is available to be acquired.
-        */
-       void *pl330_chid;
+       spin_lock_init(&pl330->lock);
 
-       /* For D-to-M and M-to-D channels */
-       int burst_sz; /* the peripheral fifo width */
-       int burst_len; /* the number of burst */
-       dma_addr_t fifo_addr;
+       INIT_LIST_HEAD(&pl330->req_done);
 
-       /* for cyclic capability */
-       bool cyclic;
-};
+       /* Use default MC buffer size if not provided */
+       if (!pi->mcbufsz)
+               pi->mcbufsz = MCODE_BUFF_PER_REQ * 2;
 
-struct dma_pl330_dmac {
-       struct pl330_info pif;
+       /* Mark all events as free */
+       for (i = 0; i < pi->pcfg.num_events; i++)
+               pl330->events[i] = -1;
 
-       /* DMA-Engine Device */
-       struct dma_device ddma;
+       /* Allocate resources needed by the DMAC */
+       ret = dmac_alloc_resources(pl330);
+       if (ret) {
+               dev_err(pi->dev, "Unable to create channels for DMAC\n");
+               kfree(pl330);
+               return ret;
+       }
 
-       /* Pool of descriptors available for the DMAC's channels */
-       struct list_head desc_pool;
-       /* To protect desc_pool manipulation */
-       spinlock_t pool_lock;
+       tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330);
 
-       /* Peripheral channels connected to this DMAC */
-       struct dma_pl330_chan *peripherals; /* keep at end */
+       pl330->state = INIT;
 
-       struct clk *clk;
-};
+       return 0;
+}
 
-struct dma_pl330_desc {
-       /* To attach to a queue as child */
-       struct list_head node;
+static int dmac_free_threads(struct pl330_dmac *pl330)
+{
+       struct pl330_info *pi = pl330->pinfo;
+       int chans = pi->pcfg.num_chan;
+       struct pl330_thread *thrd;
+       int i;
 
-       /* Descriptor for the DMA Engine API */
-       struct dma_async_tx_descriptor txd;
+       /* Release Channel threads */
+       for (i = 0; i < chans; i++) {
+               thrd = &pl330->channels[i];
+               pl330_release_channel((void *)thrd);
+       }
 
-       /* Xfer for PL330 core */
-       struct pl330_xfer px;
+       /* Free memory */
+       kfree(pl330->channels);
 
-       struct pl330_reqcfg rqcfg;
-       struct pl330_req req;
+       return 0;
+}
 
-       enum desc_status status;
+static void dmac_free_resources(struct pl330_dmac *pl330)
+{
+       struct pl330_info *pi = pl330->pinfo;
+       int chans = pi->pcfg.num_chan;
 
-       /* The channel which currently holds this desc */
-       struct dma_pl330_chan *pchan;
-};
+       dmac_free_threads(pl330);
+
+       dma_free_coherent(pi->dev, chans * pi->mcbufsz,
+                               pl330->mcode_cpu, pl330->mcode_bus);
+}
+
+static void pl330_del(struct pl330_info *pi)
+{
+       struct pl330_dmac *pl330;
+
+       if (!pi || !pi->pl330_data)
+               return;
+
+       pl330 = pi->pl330_data;
+
+       pl330->state = UNINIT;
+
+       tasklet_kill(&pl330->tasks);
+
+       /* Free DMAC resources */
+       dmac_free_resources(pl330);
+
+       kfree(pl330);
+       pi->pl330_data = NULL;
+}
 
 /* forward declaration */
 static struct amba_driver pl330_driver;
@@ -234,7 +2320,7 @@ static void pl330_tasklet(unsigned long data)
        /* Pick up ripe tomatoes */
        list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
                if (desc->status == DONE) {
-                       pch->completed = desc->txd.cookie;
+                       dma_cookie_complete(&desc->txd);
                        list_move_tail(&desc->node, &list);
                }
 
@@ -305,7 +2391,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 
        spin_lock_irqsave(&pch->lock, flags);
 
-       pch->completed = chan->cookie = 1;
+       dma_cookie_init(chan);
        pch->cyclic = false;
 
        pch->pl330_chid = pl330_request_channel(&pdmac->pif);
@@ -340,7 +2426,6 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
                /* Mark all desc done */
                list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
                        desc->status = DONE;
-                       pch->completed = desc->txd.cookie;
                        list_move_tail(&desc->node, &list);
                }
 
@@ -396,18 +2481,7 @@ static enum dma_status
 pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                 struct dma_tx_state *txstate)
 {
-       struct dma_pl330_chan *pch = to_pchan(chan);
-       dma_cookie_t last_done, last_used;
-       int ret;
-
-       last_done = pch->completed;
-       last_used = chan->cookie;
-
-       ret = dma_async_is_complete(cookie, last_done, last_used);
-
-       dma_set_tx_state(txstate, last_done, last_used, 0);
-
-       return ret;
+       return dma_cookie_status(chan, cookie, txstate);
 }
 
 static void pl330_issue_pending(struct dma_chan *chan)
@@ -430,26 +2504,16 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
        spin_lock_irqsave(&pch->lock, flags);
 
        /* Assign cookies to all nodes */
-       cookie = tx->chan->cookie;
-
        while (!list_empty(&last->node)) {
                desc = list_entry(last->node.next, struct dma_pl330_desc, node);
 
-               if (++cookie < 0)
-                       cookie = 1;
-               desc->txd.cookie = cookie;
+               dma_cookie_assign(&desc->txd);
 
                list_move_tail(&desc->node, &pch->work_list);
        }
 
-       if (++cookie < 0)
-               cookie = 1;
-       last->txd.cookie = cookie;
-
+       cookie = dma_cookie_assign(&last->txd);
        list_add_tail(&last->node, &pch->work_list);
-
-       tx->chan->cookie = cookie;
-
        spin_unlock_irqrestore(&pch->lock, flags);
 
        return cookie;
@@ -553,6 +2617,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
        async_tx_ack(&desc->txd);
 
        desc->req.peri = peri_id ? pch->chan.chan_id : 0;
+       desc->rqcfg.pcfg = &pch->dmac->pif.pcfg;
 
        dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
@@ -621,7 +2686,8 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 
 static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
                struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
-               size_t period_len, enum dma_transfer_direction direction)
+               size_t period_len, enum dma_transfer_direction direction,
+               void *context)
 {
        struct dma_pl330_desc *desc;
        struct dma_pl330_chan *pch = to_pchan(chan);
@@ -711,7 +2777,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 static struct dma_async_tx_descriptor *
 pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flg)
+               unsigned long flg, void *context)
 {
        struct dma_pl330_desc *first, *desc = NULL;
        struct dma_pl330_chan *pch = to_pchan(chan);
@@ -829,7 +2895,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        if (IS_ERR(pdmac->clk)) {
                dev_err(&adev->dev, "Cannot get operation clock.\n");
                ret = -EINVAL;
-               goto probe_err1;
+               goto probe_err2;
        }
 
        amba_set_drvdata(adev, pdmac);
@@ -843,11 +2909,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        ret = request_irq(irq, pl330_irq_handler, 0,
                        dev_name(&adev->dev), pi);
        if (ret)
-               goto probe_err2;
+               goto probe_err3;
 
        ret = pl330_add(pi);
        if (ret)
-               goto probe_err3;
+               goto probe_err4;
 
        INIT_LIST_HEAD(&pdmac->desc_pool);
        spin_lock_init(&pdmac->pool_lock);
@@ -904,7 +2970,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        ret = dma_async_device_register(pd);
        if (ret) {
                dev_err(&adev->dev, "unable to register DMAC\n");
-               goto probe_err4;
+               goto probe_err5;
        }
 
        dev_info(&adev->dev,
@@ -917,10 +2983,15 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
        return 0;
 
-probe_err4:
+probe_err5:
        pl330_del(pi);
-probe_err3:
+probe_err4:
        free_irq(irq, pi);
+probe_err3:
+#ifndef CONFIG_PM_RUNTIME
+       clk_disable(pdmac->clk);
+#endif
+       clk_put(pdmac->clk);
 probe_err2:
        iounmap(pi->base);
 probe_err1:
index fc457a7e8832dc8f29ed4055cc781369de4ef7aa..ced98826684ae65da86539ab6fa4dad531503aa4 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/dcr.h>
 #include <asm/dcr-regs.h>
 #include "adma.h"
+#include "../dmaengine.h"
 
 enum ppc_adma_init_code {
        PPC_ADMA_INIT_OK = 0,
@@ -1930,7 +1931,7 @@ static void __ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan)
                                if (end_of_chain && slot_cnt) {
                                        /* Should wait for ZeroSum completion */
                                        if (cookie > 0)
-                                               chan->completed_cookie = cookie;
+                                               chan->common.completed_cookie = cookie;
                                        return;
                                }
 
@@ -1960,7 +1961,7 @@ static void __ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan)
        BUG_ON(!seen_current);
 
        if (cookie > 0) {
-               chan->completed_cookie = cookie;
+               chan->common.completed_cookie = cookie;
                pr_debug("\tcompleted cookie %d\n", cookie);
        }
 
@@ -2149,22 +2150,6 @@ static int ppc440spe_adma_alloc_chan_resources(struct dma_chan *chan)
        return (i > 0) ? i : -ENOMEM;
 }
 
-/**
- * ppc440spe_desc_assign_cookie - assign a cookie
- */
-static dma_cookie_t ppc440spe_desc_assign_cookie(
-               struct ppc440spe_adma_chan *chan,
-               struct ppc440spe_adma_desc_slot *desc)
-{
-       dma_cookie_t cookie = chan->common.cookie;
-
-       cookie++;
-       if (cookie < 0)
-               cookie = 1;
-       chan->common.cookie = desc->async_tx.cookie = cookie;
-       return cookie;
-}
-
 /**
  * ppc440spe_rxor_set_region_data -
  */
@@ -2235,8 +2220,7 @@ static dma_cookie_t ppc440spe_adma_tx_submit(struct dma_async_tx_descriptor *tx)
        slots_per_op = group_start->slots_per_op;
 
        spin_lock_bh(&chan->lock);
-
-       cookie = ppc440spe_desc_assign_cookie(chan, sw_desc);
+       cookie = dma_cookie_assign(tx);
 
        if (unlikely(list_empty(&chan->chain))) {
                /* first peer */
@@ -3944,28 +3928,16 @@ static enum dma_status ppc440spe_adma_tx_status(struct dma_chan *chan,
                        dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
        struct ppc440spe_adma_chan *ppc440spe_chan;
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
        enum dma_status ret;
 
        ppc440spe_chan = to_ppc440spe_adma_chan(chan);
-       last_used = chan->cookie;
-       last_complete = ppc440spe_chan->completed_cookie;
-
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret == DMA_SUCCESS)
                return ret;
 
        ppc440spe_adma_slot_cleanup(ppc440spe_chan);
 
-       last_used = chan->cookie;
-       last_complete = ppc440spe_chan->completed_cookie;
-
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
-       return dma_async_is_complete(cookie, last_complete, last_used);
+       return dma_cookie_status(chan, cookie, txstate);
 }
 
 /**
@@ -4050,16 +4022,12 @@ static void ppc440spe_chan_start_null_xor(struct ppc440spe_adma_chan *chan)
                async_tx_ack(&sw_desc->async_tx);
                ppc440spe_desc_init_null_xor(group_start);
 
-               cookie = chan->common.cookie;
-               cookie++;
-               if (cookie <= 1)
-                       cookie = 2;
+               cookie = dma_cookie_assign(&sw_desc->async_tx);
 
                /* initialize the completed cookie to be less than
                 * the most recently used cookie
                 */
-               chan->completed_cookie = cookie - 1;
-               chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+               chan->common.completed_cookie = cookie - 1;
 
                /* channel should not be busy */
                BUG_ON(ppc440spe_chan_is_busy(chan));
@@ -4529,6 +4497,7 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
        INIT_LIST_HEAD(&chan->all_slots);
        chan->device = adev;
        chan->common.device = &adev->common;
+       dma_cookie_init(&chan->common);
        list_add_tail(&chan->common.device_node, &adev->common.channels);
        tasklet_init(&chan->irq_tasklet, ppc440spe_adma_tasklet,
                     (unsigned long)chan);
index 8ada5a812e3b4a94a57252d65abfa0950171787e..26b7a5ed9ac7ee0171e1dd90e9c96608107b29e6 100644 (file)
@@ -81,7 +81,6 @@ struct ppc440spe_adma_device {
  * @common: common dmaengine channel object members
  * @all_slots: complete domain of slots usable by the channel
  * @pending: allows batching of hardware operations
- * @completed_cookie: identifier for the most recently completed operation
  * @slots_allocated: records the actual size of the descriptor slot pool
  * @hw_chain_inited: h/w descriptor chain initialization flag
  * @irq_tasklet: bottom half where ppc440spe_adma_slot_cleanup runs
@@ -99,7 +98,6 @@ struct ppc440spe_adma_chan {
        struct list_head all_slots;
        struct ppc440spe_adma_desc_slot *last_used;
        int pending;
-       dma_cookie_t completed_cookie;
        int slots_allocated;
        int hw_chain_inited;
        struct tasklet_struct irq_tasklet;
index 812fd76e9c18e4b2b210f20125324560a873ddeb..19d7a8d3975dc0a1a6c864eba39257fd41cf2ccf 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/kdebug.h>
 #include <linux/spinlock.h>
 #include <linux/rculist.h>
+
+#include "dmaengine.h"
 #include "shdma.h"
 
 /* DMA descriptor control */
@@ -296,13 +298,7 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
        else
                power_up = false;
 
-       cookie = sh_chan->common.cookie;
-       cookie++;
-       if (cookie < 0)
-               cookie = 1;
-
-       sh_chan->common.cookie = cookie;
-       tx->cookie = cookie;
+       cookie = dma_cookie_assign(tx);
 
        /* Mark all chunks of this descriptor as submitted, move to the queue */
        list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
@@ -673,7 +669,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
 
 static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
        struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
-       enum dma_transfer_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags,
+       void *context)
 {
        struct sh_dmae_slave *param;
        struct sh_dmae_chan *sh_chan;
@@ -764,12 +761,12 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
                        cookie = tx->cookie;
 
                if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
-                       if (sh_chan->completed_cookie != desc->cookie - 1)
+                       if (sh_chan->common.completed_cookie != desc->cookie - 1)
                                dev_dbg(sh_chan->dev,
                                        "Completing cookie %d, expected %d\n",
                                        desc->cookie,
-                                       sh_chan->completed_cookie + 1);
-                       sh_chan->completed_cookie = desc->cookie;
+                                       sh_chan->common.completed_cookie + 1);
+                       sh_chan->common.completed_cookie = desc->cookie;
                }
 
                /* Call callback on the last chunk */
@@ -823,7 +820,7 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
                 * Terminating and the loop completed normally: forgive
                 * uncompleted cookies
                 */
-               sh_chan->completed_cookie = sh_chan->common.cookie;
+               sh_chan->common.completed_cookie = sh_chan->common.cookie;
 
        spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
@@ -883,23 +880,14 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
                                        struct dma_tx_state *txstate)
 {
        struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
        enum dma_status status;
        unsigned long flags;
 
        sh_dmae_chan_ld_cleanup(sh_chan, false);
 
-       /* First read completed cookie to avoid a skew */
-       last_complete = sh_chan->completed_cookie;
-       rmb();
-       last_used = chan->cookie;
-       BUG_ON(last_complete < 0);
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
        spin_lock_irqsave(&sh_chan->desc_lock, flags);
 
-       status = dma_async_is_complete(cookie, last_complete, last_used);
+       status = dma_cookie_status(chan, cookie, txstate);
 
        /*
         * If we don't find cookie on the queue, it has been aborted and we have
@@ -1102,6 +1090,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
 
        /* reference struct dma_device */
        new_sh_chan->common.device = &shdev->common;
+       dma_cookie_init(&new_sh_chan->common);
 
        new_sh_chan->dev = shdev->common.dev;
        new_sh_chan->id = id;
index 2b55a276dc5bd60503aa1d740c5451dc594f4eff..0b1d2c105f027c5a45de636bef665f321bb46968 100644 (file)
@@ -30,7 +30,6 @@ enum dmae_pm_state {
 };
 
 struct sh_dmae_chan {
-       dma_cookie_t completed_cookie;  /* The maximum cookie completed */
        spinlock_t desc_lock;           /* Descriptor operation lock */
        struct list_head ld_queue;      /* Link descriptors queue */
        struct list_head ld_free;       /* Link descriptors free */
index 2333810d1688c369f232eb6d08ee7bd17dcd0f03..434ad31174f289f6a2cc14ac6121b594d2b09207 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/of_platform.h>
 #include <linux/sirfsoc_dma.h>
 
+#include "dmaengine.h"
+
 #define SIRFSOC_DMA_DESCRIPTORS                 16
 #define SIRFSOC_DMA_CHANNELS                    16
 
@@ -59,7 +61,6 @@ struct sirfsoc_dma_chan {
        struct list_head                queued;
        struct list_head                active;
        struct list_head                completed;
-       dma_cookie_t                    completed_cookie;
        unsigned long                   happened_cyclic;
        unsigned long                   completed_cyclic;
 
@@ -208,7 +209,7 @@ static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma)
                        /* Free descriptors */
                        spin_lock_irqsave(&schan->lock, flags);
                        list_splice_tail_init(&list, &schan->free);
-                       schan->completed_cookie = last_cookie;
+                       schan->chan.completed_cookie = last_cookie;
                        spin_unlock_irqrestore(&schan->lock, flags);
                } else {
                        /* for cyclic channel, desc is always in active list */
@@ -258,13 +259,7 @@ static dma_cookie_t sirfsoc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
        /* Move descriptor to queue */
        list_move_tail(&sdesc->node, &schan->queued);
 
-       /* Update cookie */
-       cookie = schan->chan.cookie + 1;
-       if (cookie <= 0)
-               cookie = 1;
-
-       schan->chan.cookie = cookie;
-       sdesc->desc.cookie = cookie;
+       cookie = dma_cookie_assign(txd);
 
        spin_unlock_irqrestore(&schan->lock, flags);
 
@@ -414,16 +409,13 @@ sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 {
        struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
        unsigned long flags;
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
+       enum dma_status ret;
 
        spin_lock_irqsave(&schan->lock, flags);
-       last_used = schan->chan.cookie;
-       last_complete = schan->completed_cookie;
+       ret = dma_cookie_status(chan, cookie, txstate);
        spin_unlock_irqrestore(&schan->lock, flags);
 
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-       return dma_async_is_complete(cookie, last_complete, last_used);
+       return ret;
 }
 
 static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
@@ -497,7 +489,7 @@ err_dir:
 static struct dma_async_tx_descriptor *
 sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr,
        size_t buf_len, size_t period_len,
-       enum dma_transfer_direction direction)
+       enum dma_transfer_direction direction, void *context)
 {
        struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
        struct sirfsoc_dma_desc *sdesc = NULL;
@@ -635,8 +627,7 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
                schan = &sdma->channels[i];
 
                schan->chan.device = dma;
-               schan->chan.cookie = 1;
-               schan->completed_cookie = schan->chan.cookie;
+               dma_cookie_init(&schan->chan);
 
                INIT_LIST_HEAD(&schan->free);
                INIT_LIST_HEAD(&schan->prepared);
index cc5ecbc067a3d8a8d88c97190b0248fb0851593b..bdd41d4bfa8d8f8bd129e4efffbf0b7187755fa1 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <plat/ste_dma40.h>
 
+#include "dmaengine.h"
 #include "ste_dma40_ll.h"
 
 #define D40_NAME "dma40"
@@ -220,8 +221,6 @@ struct d40_base;
  *
  * @lock: A spinlock to protect this struct.
  * @log_num: The logical number, if any of this channel.
- * @completed: Starts with 1, after first interrupt it is set to dma engine's
- * current cookie.
  * @pending_tx: The number of pending transfers. Used between interrupt handler
  * and tasklet.
  * @busy: Set to true when transfer is ongoing on this channel.
@@ -250,8 +249,6 @@ struct d40_base;
 struct d40_chan {
        spinlock_t                       lock;
        int                              log_num;
-       /* ID of the most recent completed transfer */
-       int                              completed;
        int                              pending_tx;
        bool                             busy;
        struct d40_phy_res              *phy_chan;
@@ -1223,21 +1220,14 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
                                             chan);
        struct d40_desc *d40d = container_of(tx, struct d40_desc, txd);
        unsigned long flags;
+       dma_cookie_t cookie;
 
        spin_lock_irqsave(&d40c->lock, flags);
-
-       d40c->chan.cookie++;
-
-       if (d40c->chan.cookie < 0)
-               d40c->chan.cookie = 1;
-
-       d40d->txd.cookie = d40c->chan.cookie;
-
+       cookie = dma_cookie_assign(tx);
        d40_desc_queue(d40c, d40d);
-
        spin_unlock_irqrestore(&d40c->lock, flags);
 
-       return tx->cookie;
+       return cookie;
 }
 
 static int d40_start(struct d40_chan *d40c)
@@ -1357,7 +1347,7 @@ static void dma_tasklet(unsigned long data)
                goto err;
 
        if (!d40d->cyclic)
-               d40c->completed = d40d->txd.cookie;
+               dma_cookie_complete(&d40d->txd);
 
        /*
         * If terminating a channel pending_tx is set to zero.
@@ -2182,7 +2172,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
        bool is_free_phy;
        spin_lock_irqsave(&d40c->lock, flags);
 
-       d40c->completed = chan->cookie = 1;
+       dma_cookie_init(chan);
 
        /* If no dma configuration is set use default configuration (memcpy) */
        if (!d40c->configured) {
@@ -2299,7 +2289,8 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
                                                         struct scatterlist *sgl,
                                                         unsigned int sg_len,
                                                         enum dma_transfer_direction direction,
-                                                        unsigned long dma_flags)
+                                                        unsigned long dma_flags,
+                                                        void *context)
 {
        if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV)
                return NULL;
@@ -2310,7 +2301,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
 static struct dma_async_tx_descriptor *
 dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
                     size_t buf_len, size_t period_len,
-                    enum dma_transfer_direction direction)
+                    enum dma_transfer_direction direction, void *context)
 {
        unsigned int periods = buf_len / period_len;
        struct dma_async_tx_descriptor *txd;
@@ -2342,25 +2333,19 @@ static enum dma_status d40_tx_status(struct dma_chan *chan,
                                     struct dma_tx_state *txstate)
 {
        struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
-       int ret;
+       enum dma_status ret;
 
        if (d40c->phy_chan == NULL) {
                chan_err(d40c, "Cannot read status of unallocated channel\n");
                return -EINVAL;
        }
 
-       last_complete = d40c->completed;
-       last_used = chan->cookie;
+       ret = dma_cookie_status(chan, cookie, txstate);
+       if (ret != DMA_SUCCESS)
+               dma_set_residue(txstate, stedma40_residue(chan));
 
        if (d40_is_paused(d40c))
                ret = DMA_PAUSED;
-       else
-               ret = dma_async_is_complete(cookie, last_complete, last_used);
-
-       dma_set_tx_state(txstate, last_complete, last_used,
-                        stedma40_residue(chan));
 
        return ret;
 }
index a6f9c1684a0fc1dc4a9c7a2dbd2407fe6252b68d..4e0dff59901da8e008f6a004b5f670228fae00f9 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <linux/timb_dma.h>
 
+#include "dmaengine.h"
+
 #define DRIVER_NAME "timb-dma"
 
 /* Global DMA registers */
@@ -84,7 +86,6 @@ struct timb_dma_chan {
                                        especially the lists and descriptors,
                                        from races between the tasklet and calls
                                        from above */
-       dma_cookie_t            last_completed_cookie;
        bool                    ongoing;
        struct list_head        active_list;
        struct list_head        queue;
@@ -284,7 +285,7 @@ static void __td_finish(struct timb_dma_chan *td_chan)
        else
                iowrite32(0, td_chan->membase + TIMBDMA_OFFS_TX_DLAR);
 */
-       td_chan->last_completed_cookie = txd->cookie;
+       dma_cookie_complete(txd);
        td_chan->ongoing = false;
 
        callback = txd->callback;
@@ -349,12 +350,7 @@ static dma_cookie_t td_tx_submit(struct dma_async_tx_descriptor *txd)
        dma_cookie_t cookie;
 
        spin_lock_bh(&td_chan->lock);
-
-       cookie = txd->chan->cookie;
-       if (++cookie < 0)
-               cookie = 1;
-       txd->chan->cookie = cookie;
-       txd->cookie = cookie;
+       cookie = dma_cookie_assign(txd);
 
        if (list_empty(&td_chan->active_list)) {
                dev_dbg(chan2dev(txd->chan), "%s: started %u\n", __func__,
@@ -481,8 +477,7 @@ static int td_alloc_chan_resources(struct dma_chan *chan)
        }
 
        spin_lock_bh(&td_chan->lock);
-       td_chan->last_completed_cookie = 1;
-       chan->cookie = 1;
+       dma_cookie_init(chan);
        spin_unlock_bh(&td_chan->lock);
 
        return 0;
@@ -515,24 +510,13 @@ static void td_free_chan_resources(struct dma_chan *chan)
 static enum dma_status td_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                                    struct dma_tx_state *txstate)
 {
-       struct timb_dma_chan *td_chan =
-               container_of(chan, struct timb_dma_chan, chan);
-       dma_cookie_t            last_used;
-       dma_cookie_t            last_complete;
-       int                     ret;
+       enum dma_status ret;
 
        dev_dbg(chan2dev(chan), "%s: Entry\n", __func__);
 
-       last_complete = td_chan->last_completed_cookie;
-       last_used = chan->cookie;
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
-
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
+       ret = dma_cookie_status(chan, cookie, txstate);
 
-       dev_dbg(chan2dev(chan),
-               "%s: exit, ret: %d, last_complete: %d, last_used: %d\n",
-               __func__, ret, last_complete, last_used);
+       dev_dbg(chan2dev(chan), "%s: exit, ret: %d\n",  __func__, ret);
 
        return ret;
 }
@@ -558,7 +542,8 @@ static void td_issue_pending(struct dma_chan *chan)
 
 static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan,
        struct scatterlist *sgl, unsigned int sg_len,
-       enum dma_transfer_direction direction, unsigned long flags)
+       enum dma_transfer_direction direction, unsigned long flags,
+       void *context)
 {
        struct timb_dma_chan *td_chan =
                container_of(chan, struct timb_dma_chan, chan);
@@ -766,7 +751,7 @@ static int __devinit td_probe(struct platform_device *pdev)
                }
 
                td_chan->chan.device = &td->dma;
-               td_chan->chan.cookie = 1;
+               dma_cookie_init(&td_chan->chan);
                spin_lock_init(&td_chan->lock);
                INIT_LIST_HEAD(&td_chan->active_list);
                INIT_LIST_HEAD(&td_chan->queue);
index 6122c364cf11bb0050fb2b029c083b3c40233722..913f55c76c9915bfb08bde041afdc2d9a7d7590f 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/scatterlist.h>
+
+#include "dmaengine.h"
 #include "txx9dmac.h"
 
 static struct txx9dmac_chan *to_txx9dmac_chan(struct dma_chan *chan)
@@ -279,21 +281,6 @@ static void txx9dmac_desc_put(struct txx9dmac_chan *dc,
        }
 }
 
-/* Called with dc->lock held and bh disabled */
-static dma_cookie_t
-txx9dmac_assign_cookie(struct txx9dmac_chan *dc, struct txx9dmac_desc *desc)
-{
-       dma_cookie_t cookie = dc->chan.cookie;
-
-       if (++cookie < 0)
-               cookie = 1;
-
-       dc->chan.cookie = cookie;
-       desc->txd.cookie = cookie;
-
-       return cookie;
-}
-
 /*----------------------------------------------------------------------*/
 
 static void txx9dmac_dump_regs(struct txx9dmac_chan *dc)
@@ -424,7 +411,7 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
        dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
                 txd->cookie, desc);
 
-       dc->completed = txd->cookie;
+       dma_cookie_complete(txd);
        callback = txd->callback;
        param = txd->callback_param;
 
@@ -738,7 +725,7 @@ static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx)
        dma_cookie_t cookie;
 
        spin_lock_bh(&dc->lock);
-       cookie = txx9dmac_assign_cookie(dc, desc);
+       cookie = dma_cookie_assign(tx);
 
        dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u %p\n",
                 desc->txd.cookie, desc);
@@ -846,7 +833,7 @@ txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 static struct dma_async_tx_descriptor *
 txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags)
+               unsigned long flags, void *context)
 {
        struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
        struct txx9dmac_dev *ddev = dc->ddev;
@@ -972,27 +959,17 @@ txx9dmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                   struct dma_tx_state *txstate)
 {
        struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
-       dma_cookie_t last_used;
-       dma_cookie_t last_complete;
-       int ret;
+       enum dma_status ret;
 
-       last_complete = dc->completed;
-       last_used = chan->cookie;
-
-       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       ret = dma_cookie_status(chan, cookie, txstate);
        if (ret != DMA_SUCCESS) {
                spin_lock_bh(&dc->lock);
                txx9dmac_scan_descriptors(dc);
                spin_unlock_bh(&dc->lock);
 
-               last_complete = dc->completed;
-               last_used = chan->cookie;
-
-               ret = dma_async_is_complete(cookie, last_complete, last_used);
+               ret = dma_cookie_status(chan, cookie, txstate);
        }
 
-       dma_set_tx_state(txstate, last_complete, last_used, 0);
-
        return ret;
 }
 
@@ -1057,7 +1034,7 @@ static int txx9dmac_alloc_chan_resources(struct dma_chan *chan)
                return -EIO;
        }
 
-       dc->completed = chan->cookie = 1;
+       dma_cookie_init(chan);
 
        dc->ccr = TXX9_DMA_CCR_IMMCHN | TXX9_DMA_CCR_INTENE | CCR_LE;
        txx9dmac_chan_set_SMPCHN(dc);
@@ -1186,7 +1163,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev)
        dc->ddev->chan[ch] = dc;
        dc->chan.device = &dc->dma;
        list_add_tail(&dc->chan.device_node, &dc->chan.device->channels);
-       dc->chan.cookie = dc->completed = 1;
+       dma_cookie_init(&dc->chan);
 
        if (is_dmac64(dc))
                dc->ch_regs = &__txx9dmac_regs(dc->ddev)->CHAN[ch];
index 365d42366b9f15e237833ace8530e1f4e78e1a21..f5a760598882499ff73174ffcb2b5b486606056d 100644 (file)
@@ -172,7 +172,6 @@ struct txx9dmac_chan {
        spinlock_t              lock;
 
        /* these other elements are all protected by lock */
-       dma_cookie_t            completed;
        struct list_head        active_list;
        struct list_head        queue;
        struct list_head        free_list;
index 5948a2194f503e80e19f2ab55e8a22cc096c9e75..fdffa1beca17288eeab2055d25382545c3dbbdcf 100644 (file)
@@ -215,7 +215,7 @@ config EDAC_I7300
 config EDAC_SBRIDGE
        tristate "Intel Sandy-Bridge Integrated MC"
        depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
-       depends on EXPERIMENTAL
+       depends on PCI_MMCONFIG && EXPERIMENTAL
        help
          Support for error detection and correction the Intel
          Sandy Bridge Integrated Memory Controller.
index da09cd74bc5b10766da646d8d712c9eab6bd75e3..feef7733fae7702733feb642bfcf0ac7c431f484 100644 (file)
@@ -39,7 +39,7 @@ static LIST_HEAD(mc_devices);
 
 #ifdef CONFIG_EDAC_DEBUG
 
-static void edac_mc_dump_channel(struct channel_info *chan)
+static void edac_mc_dump_channel(struct rank_info *chan)
 {
        debugf4("\tchannel = %p\n", chan);
        debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
@@ -156,7 +156,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
 {
        struct mem_ctl_info *mci;
        struct csrow_info *csi, *csrow;
-       struct channel_info *chi, *chp, *chan;
+       struct rank_info *chi, *chp, *chan;
        void *pvt;
        unsigned size;
        int row, chn;
@@ -181,7 +181,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
         * rather than an imaginary chunk of memory located at address 0.
         */
        csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi));
-       chi = (struct channel_info *)(((char *)mci) + ((unsigned long)chi));
+       chi = (struct rank_info *)(((char *)mci) + ((unsigned long)chi));
        pvt = sz_pvt ? (((char *)mci) + ((unsigned long)pvt)) : NULL;
 
        /* setup index and various internal pointers */
index 2e23547b2f24ed40f85cd39bda1686e197d9d6dd..d500749464ea6038e147f25404586c1289d28b1d 100644 (file)
@@ -49,7 +49,7 @@
 #define                I5100_FERR_NF_MEM_M6ERR_MASK    (1 << 6)
 #define                I5100_FERR_NF_MEM_M5ERR_MASK    (1 << 5)
 #define                I5100_FERR_NF_MEM_M4ERR_MASK    (1 << 4)
-#define                I5100_FERR_NF_MEM_M1ERR_MASK    1
+#define                I5100_FERR_NF_MEM_M1ERR_MASK    (1 << 1)
 #define                I5100_FERR_NF_MEM_ANY_MASK      \
                        (I5100_FERR_NF_MEM_M16ERR_MASK | \
                        I5100_FERR_NF_MEM_M15ERR_MASK | \
@@ -535,23 +535,20 @@ static void i5100_read_log(struct mem_ctl_info *mci, int chan,
 static void i5100_check_error(struct mem_ctl_info *mci)
 {
        struct i5100_priv *priv = mci->pvt_info;
-       u32 dw;
-
+       u32 dw, dw2;
 
        pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw);
        if (i5100_ferr_nf_mem_any(dw)) {
-               u32 dw2;
 
                pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2);
-               if (dw2)
-                       pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM,
-                                              dw2);
-               pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
 
                i5100_read_log(mci, i5100_ferr_nf_mem_chan_indx(dw),
                               i5100_ferr_nf_mem_any(dw),
                               i5100_nerr_nf_mem_any(dw2));
+
+               pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM, dw2);
        }
+       pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
 }
 
 /* The i5100 chipset will scrub the entire memory once, then
index 67ec9626a33055377d71ccffa1067efdf3ac3a47..1869a1018fb5215b51e80ce53c274ae5c1190566 100644 (file)
@@ -735,7 +735,7 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
 
        /* Attempt to 'get' the MCH register we want */
        pdev = NULL;
-       while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) {
+       while (1) {
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
                if (!pdev) {
@@ -743,23 +743,42 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
                        i5400_printk(KERN_ERR,
                                "'system address,Process Bus' "
                                "device not found:"
-                               "vendor 0x%x device 0x%x ERR funcs "
+                               "vendor 0x%x device 0x%x ERR func 1 "
                                "(broken BIOS?)\n",
                                PCI_VENDOR_ID_INTEL,
                                PCI_DEVICE_ID_INTEL_5400_ERR);
-                       goto error;
+                       return -ENODEV;
                }
 
-               /* Store device 16 funcs 1 and 2 */
-               switch (PCI_FUNC(pdev->devfn)) {
-               case 1:
-                       pvt->branchmap_werrors = pdev;
-                       break;
-               case 2:
-                       pvt->fsb_error_regs = pdev;
+               /* Store device 16 func 1 */
+               if (PCI_FUNC(pdev->devfn) == 1)
                        break;
+       }
+       pvt->branchmap_werrors = pdev;
+
+       pdev = NULL;
+       while (1) {
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
+               if (!pdev) {
+                       /* End of list, leave */
+                       i5400_printk(KERN_ERR,
+                               "'system address,Process Bus' "
+                               "device not found:"
+                               "vendor 0x%x device 0x%x ERR func 2 "
+                               "(broken BIOS?)\n",
+                               PCI_VENDOR_ID_INTEL,
+                               PCI_DEVICE_ID_INTEL_5400_ERR);
+
+                       pci_dev_put(pvt->branchmap_werrors);
+                       return -ENODEV;
                }
+
+               /* Store device 16 func 2 */
+               if (PCI_FUNC(pdev->devfn) == 2)
+                       break;
        }
+       pvt->fsb_error_regs = pdev;
 
        debugf1("System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
                pci_name(pvt->system_address),
@@ -778,7 +797,10 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
                        "MC: 'BRANCH 0' device not found:"
                        "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
                        PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0);
-               goto error;
+
+               pci_dev_put(pvt->fsb_error_regs);
+               pci_dev_put(pvt->branchmap_werrors);
+               return -ENODEV;
        }
 
        /* If this device claims to have more than 2 channels then
@@ -796,14 +818,14 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
                        "(broken BIOS?)\n",
                        PCI_VENDOR_ID_INTEL,
                        PCI_DEVICE_ID_INTEL_5400_FBD1);
-               goto error;
+
+               pci_dev_put(pvt->branch_0);
+               pci_dev_put(pvt->fsb_error_regs);
+               pci_dev_put(pvt->branchmap_werrors);
+               return -ENODEV;
        }
 
        return 0;
-
-error:
-       i5400_put_devices(mci);
-       return -ENODEV;
 }
 
 /*
index fc757069c6af61672fdf51e3e471d9e0dddfa527..d427c69bb8b1ebf811b4aeadcf06ac532b3be4b1 100644 (file)
@@ -184,7 +184,7 @@ struct ppc4xx_ecc_status {
 
 /* Function Prototypes */
 
-static int ppc4xx_edac_probe(struct platform_device *device)
+static int ppc4xx_edac_probe(struct platform_device *device);
 static int ppc4xx_edac_remove(struct platform_device *device);
 
 /* Global Variables */
@@ -1068,7 +1068,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
 
        mci->mod_name           = PPC4XX_EDAC_MODULE_NAME;
        mci->mod_ver            = PPC4XX_EDAC_MODULE_REVISION;
-       mci->ctl_name           = match->compatible,
+       mci->ctl_name           = ppc4xx_edac_match->compatible,
        mci->dev_name           = np->full_name;
 
        /* Initialize callbacks */
index 3a605f77771250da86d56009f18e1fa354399a0c..a203536d90dd613992b859c6889784b7153e46d5 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mmzone.h>
 #include <linux/smp.h>
 #include <linux/bitmap.h>
+#include <linux/math64.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 
@@ -670,6 +671,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        u32 reg;
        u64 limit, prv = 0;
        u64 tmp_mb;
+       u32 mb, kb;
        u32 rir_way;
 
        /*
@@ -682,8 +684,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        pvt->tolm = GET_TOLM(reg);
        tmp_mb = (1 + pvt->tolm) >> 20;
 
-       debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
-               tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+       mb = div_u64_rem(tmp_mb, 1000, &kb);
+       debugf0("TOLM: %u.%03u GB (0x%016Lx)\n",
+               mb, kb, (u64)pvt->tolm);
 
        /* Address range is already 45:25 */
        pci_read_config_dword(pvt->pci_sad1, TOHM,
@@ -691,8 +694,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        pvt->tohm = GET_TOHM(reg);
        tmp_mb = (1 + pvt->tohm) >> 20;
 
-       debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
-               tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+       mb = div_u64_rem(tmp_mb, 1000, &kb);
+       debugf0("TOHM: %u.%03u GB (0x%016Lx)",
+               mb, kb, (u64)pvt->tohm);
 
        /*
         * Step 2) Get SAD range and SAD Interleave list
@@ -714,10 +718,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        break;
 
                tmp_mb = (limit + 1) >> 20;
-               debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+               mb = div_u64_rem(tmp_mb, 1000, &kb);
+               debugf0("SAD#%d %s up to %u.%03u GB (0x%016Lx) %s reg=0x%08x\n",
                        n_sads,
                        get_dram_attr(reg),
-                       tmp_mb / 1000, tmp_mb % 1000,
+                       mb, kb,
                        ((u64)tmp_mb) << 20L,
                        INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
                        reg);
@@ -747,8 +752,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        break;
                tmp_mb = (limit + 1) >> 20;
 
-               debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
-                       n_tads, tmp_mb / 1000, tmp_mb % 1000,
+               mb = div_u64_rem(tmp_mb, 1000, &kb);
+               debugf0("TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+                       n_tads, mb, kb,
                        ((u64)tmp_mb) << 20L,
                        (u32)TAD_SOCK(reg),
                        (u32)TAD_CH(reg),
@@ -757,7 +763,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        (u32)TAD_TGT2(reg),
                        (u32)TAD_TGT3(reg),
                        reg);
-               prv = tmp_mb;
+               prv = limit;
        }
 
        /*
@@ -771,9 +777,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                              tad_ch_nilv_offset[j],
                                              &reg);
                        tmp_mb = TAD_OFFSET(reg) >> 20;
-                       debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+                       mb = div_u64_rem(tmp_mb, 1000, &kb);
+                       debugf0("TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n",
                                i, j,
-                               tmp_mb / 1000, tmp_mb % 1000,
+                               mb, kb,
                                ((u64)tmp_mb) << 20L,
                                reg);
                }
@@ -795,9 +802,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
 
                        tmp_mb = RIR_LIMIT(reg) >> 20;
                        rir_way = 1 << RIR_WAY(reg);
-                       debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+                       mb = div_u64_rem(tmp_mb, 1000, &kb);
+                       debugf0("CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
                                i, j,
-                               tmp_mb / 1000, tmp_mb % 1000,
+                               mb, kb,
                                ((u64)tmp_mb) << 20L,
                                rir_way,
                                reg);
@@ -808,9 +816,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                                      &reg);
                                tmp_mb = RIR_OFFSET(reg) << 6;
 
-                               debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+                               mb = div_u64_rem(tmp_mb, 1000, &kb);
+                               debugf0("CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
                                        i, j, k,
-                                       tmp_mb / 1000, tmp_mb % 1000,
+                                       mb, kb,
                                        ((u64)tmp_mb) << 20L,
                                        (u32)RIR_RNK_TGT(reg),
                                        reg);
@@ -848,6 +857,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        u8                      ch_way,sck_way;
        u32                     tad_offset;
        u32                     rir_way;
+       u32                     mb, kb;
        u64                     ch_addr, offset, limit, prv = 0;
 
 
@@ -858,7 +868,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
         * range (e. g. VGA addresses). It is unlikely, however, that the
         * memory controller would generate an error on that range.
         */
-       if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+       if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) {
                sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
                edac_mc_handle_ce_no_info(mci, msg);
                return -EINVAL;
@@ -913,7 +923,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                addr,
                limit,
                sad_way + 7,
-               INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
+               interleave_mode ? "" : "XOR[18:16]");
        if (interleave_mode)
                idx = ((addr >> 6) ^ (addr >> 16)) & 7;
        else
@@ -1053,7 +1063,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        ch_addr = addr & 0x7f;
        /* Remove socket wayness and remove 6 bits */
        addr >>= 6;
-       addr /= sck_xch;
+       addr = div_u64(addr, sck_xch);
 #if 0
        /* Divide by channel way */
        addr = addr / ch_way;
@@ -1073,10 +1083,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                        continue;
 
                limit = RIR_LIMIT(reg);
-
-               debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+               mb = div_u64_rem(limit >> 20, 1000, &kb);
+               debugf0("RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
                        n_rir,
-                       (limit >> 20) / 1000, (limit >> 20) % 1000,
+                       mb, kb,
                        limit,
                        1 << RIR_WAY(reg));
                if  (ch_addr <= limit)
index 22c6df5f136d3a631483cb5879d5aca2eb16eecf..2e6b24547e2a79dd701e235f60f48f4342633841 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 
-#include <asm/system.h>
 
 #include "core.h"
 
index afa7c83bd1146032031a93e571939b51809176c7..68109e9bb04e4395bdbeadc02e0edfa9229074a8 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <linux/atomic.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #include "core.h"
 
index 255646ffc3528df70aeccbbfc291bcc4695404fa..0de83508f321c18b973ed9fc548471ddf69391da 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <linux/atomic.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #include "core.h"
 
index 187b3f2e797e8377662677457c1bd89870befef9..2b5460075a9fc47a84c9f0a79a06c15519a976b9 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/pmac_feature.h>
index 000a29ffedaed767519f4f39ef3ca293bfeb3c5a..b7e65d7eab6465e982722553696c51cb71d3a5ec 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index 0409cf35adda246f944c7173b219640aa23be3c6..edadbdad31d04c2f228166afa8f1971f21573044 100644 (file)
@@ -236,6 +236,12 @@ config GPIO_MAX732X_IRQ
          Say yes here to enable the max732x to be used as an interrupt
          controller. It requires the driver to be built in the kernel.
 
+config GPIO_MC9S08DZ60
+       bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
+       depends on I2C && MACH_MX35_3DS
+       help
+         Select this to enable the MC9S08DZ60 GPIO driver
+
 config GPIO_PCA953X
        tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
        depends on I2C
@@ -422,6 +428,14 @@ config GPIO_ML_IOH
          Hub) which is for IVI(In-Vehicle Infotainment) use.
          This driver can access the IOH's GPIO device.
 
+config GPIO_SODAVILLE
+       bool "Intel Sodaville GPIO support"
+       depends on X86 && PCI && OF && BROKEN
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+       help
+         Say Y here to support Intel Sodaville GPIO.
+
 config GPIO_TIMBERDALE
        bool "Support for timberdale GPIO IP"
        depends on MFD_TIMBERDALE && HAS_IOMEM
index 9a8fb54ae462df9b48b40e4e12c6eb22dcf31e97..007f54bd0081203dcf04ec775254b6b72c8d422f 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_MAX7300)    += gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)     += gpio-max7301.o
 obj-$(CONFIG_GPIO_MAX732X)     += gpio-max732x.o
 obj-$(CONFIG_GPIO_MC33880)     += gpio-mc33880.o
+obj-$(CONFIG_GPIO_MC9S08DZ60)  += gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
@@ -46,6 +47,7 @@ obj-$(CONFIG_GPIO_RDC321X)    += gpio-rdc321x.o
 obj-$(CONFIG_PLAT_SAMSUNG)     += gpio-samsung.o
 obj-$(CONFIG_ARCH_SA1100)      += gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)         += gpio-sch.o
+obj-$(CONFIG_GPIO_SODAVILLE)   += gpio-sodaville.o
 obj-$(CONFIG_GPIO_STMPE)       += gpio-stmpe.o
 obj-$(CONFIG_GPIO_SX150X)      += gpio-sx150x.o
 obj-$(CONFIG_GPIO_TC3589X)     += gpio-tc3589x.o
index df0d59570a8410ac4ae1dfa89bed1c016ef3c2e5..3d000169285d69cb1993882ed3f573cbda0d2b58 100644 (file)
@@ -313,10 +313,16 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
                return -ENODEV;
 }
 
-static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
+static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
 {
-       struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-       u32 mask = (u32) irq_data_get_irq_handler_data(d);
+       struct davinci_gpio_controller *d;
+       struct davinci_gpio_regs __iomem *g;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
+       u32 mask;
+
+       d = (struct davinci_gpio_controller *)data->handler_data;
+       g = (struct davinci_gpio_regs __iomem *)d->regs;
+       mask = __gpio_mask(data->irq - soc_info->gpio_irq);
 
        if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                return -EINVAL;
@@ -380,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void)
         * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
         */
        if (soc_info->gpio_unbanked) {
-               static struct irq_chip gpio_irqchip_unbanked;
+               static struct irq_chip_type gpio_unbanked;
 
                /* pass "bank 0" GPIO IRQs to AINTC */
                chips[0].chip.to_irq = gpio_to_irq_unbanked;
@@ -388,9 +394,10 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
                irq = bank_irq;
-               gpio_irqchip_unbanked = *irq_get_chip(irq);
-               gpio_irqchip_unbanked.name = "GPIO-AINTC";
-               gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
+               gpio_unbanked = *container_of(irq_get_chip(irq),
+                                             struct irq_chip_type, chip);
+               gpio_unbanked.chip.name = "GPIO-AINTC";
+               gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked;
 
                /* default trigger: both edges */
                g = gpio2regs(0);
@@ -399,9 +406,8 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* set the direct IRQs up to use that irqchip */
                for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-                       irq_set_chip(irq, &gpio_irqchip_unbanked);
-                       irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
-                       irq_set_chip_data(irq, (__force void *)g);
+                       irq_set_chip(irq, &gpio_unbanked.chip);
+                       irq_set_handler_data(irq, &chips[gpio / 32]);
                        irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
                }
 
index 4ca5642e9776108b5ba873be4faa0dd37e3c08ac..776b772523e5039f81440d412397aaabac49c544 100644 (file)
@@ -12,8 +12,6 @@
  *  published by the Free Software Foundation.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -65,11 +63,6 @@ static void ep93xx_gpio_update_int_params(unsigned port)
                EP93XX_GPIO_REG(int_en_register_offset[port]));
 }
 
-static inline void ep93xx_gpio_int_mask(unsigned line)
-{
-       gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
-}
-
 static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
 {
        int line = irq_to_gpio(irq);
@@ -212,7 +205,6 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
                handler = handle_edge_irq;
                break;
        default:
-               pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
                return -EINVAL;
        }
 
index ddfacc5ce56d55fce87d0131e535b27671ed5828..61c2d08d37b60ae145abd782fe917ff959c0264a 100644 (file)
 #define GPO3_PIN_TO_BIT(x)                     (1 << (x))
 #define GPIO012_PIN_IN_SEL(x, y)               (((x) >> (y)) & 1)
 #define GPIO3_PIN_IN_SHIFT(x)                  ((x) == 5 ? 24 : 10 + (x))
-#define GPIO3_PIN_IN_SEL(x, y)                 ((x) >> GPIO3_PIN_IN_SHIFT(y))
+#define GPIO3_PIN_IN_SEL(x, y)                 (((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)
 #define GPIO3_PIN5_IN_SEL(x)                   (((x) >> 24) & 1)
 #define GPI3_PIN_IN_SEL(x, y)                  (((x) >> (y)) & 1)
+#define GPO3_PIN_IN_SEL(x, y)                  (((x) >> (y)) & 1)
 
 struct gpio_regs {
        void __iomem *inp_state;
+       void __iomem *outp_state;
        void __iomem *outp_set;
        void __iomem *outp_clr;
        void __iomem *dir_set;
@@ -145,6 +147,7 @@ static struct gpio_regs gpio_grp_regs_p2 = {
 
 static struct gpio_regs gpio_grp_regs_p3 = {
        .inp_state      = LPC32XX_GPIO_P3_INP_STATE,
+       .outp_state     = LPC32XX_GPIO_P3_OUTP_STATE,
        .outp_set       = LPC32XX_GPIO_P3_OUTP_SET,
        .outp_clr       = LPC32XX_GPIO_P3_OUTP_CLR,
        .dir_set        = LPC32XX_GPIO_P2_DIR_SET,
@@ -240,6 +243,12 @@ static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
        return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
 }
 
+static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
+       unsigned pin)
+{
+       return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin);
+}
+
 /*
  * GENERIC_GPIO primitives.
  */
@@ -340,6 +349,13 @@ static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
        __set_gpo_level_p3(group, pin, value);
 }
 
+static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)
+{
+       struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+       return __get_gpo_state_p3(group, pin);
+}
+
 static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
 {
        if (pin < chip->ngpio)
@@ -427,6 +443,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
                        .label                  = "gpo_p3",
                        .direction_output       = lpc32xx_gpio_dir_out_always,
                        .set                    = lpc32xx_gpo_set_value,
+                       .get                    = lpc32xx_gpo_get_value,
                        .request                = lpc32xx_gpio_request,
                        .base                   = LPC32XX_GPO_P3_GRP,
                        .ngpio                  = LPC32XX_GPO_P3_MAX,
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c
new file mode 100644 (file)
index 0000000..2738cc4
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Author: Wu Guoxing <b39297@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+
+#define GPIO_GROUP_NUM 2
+#define GPIO_NUM_PER_GROUP 8
+#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
+
+struct mc9s08dz60 {
+       struct i2c_client *client;
+       struct gpio_chip chip;
+};
+
+static inline struct mc9s08dz60 *to_mc9s08dz60(struct gpio_chip *gc)
+{
+       return container_of(gc, struct mc9s08dz60, chip);
+}
+
+
+static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
+{
+       *reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
+       *bit = offset % GPIO_NUM_PER_GROUP;
+}
+
+static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
+{
+       u8 reg, bit;
+       s32 value;
+       struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
+
+       mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
+       value = i2c_smbus_read_byte_data(mc9s->client, reg);
+
+       return (value >= 0) ? (value >> bit) & 0x1 : 0;
+}
+
+static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
+{
+       u8 reg, bit;
+       s32 value;
+
+       mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
+       value = i2c_smbus_read_byte_data(mc9s->client, reg);
+       if (value >= 0) {
+               if (val)
+                       value |= 1 << bit;
+               else
+                       value &= ~(1 << bit);
+
+               return i2c_smbus_write_byte_data(mc9s->client, reg, value);
+       } else
+               return value;
+
+}
+
+
+static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
+{
+       struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
+
+       mc9s08dz60_set(mc9s, offset, val);
+}
+
+static int mc9s08dz60_direction_output(struct gpio_chip *gc,
+                                      unsigned offset, int val)
+{
+       struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
+
+       return mc9s08dz60_set(mc9s, offset, val);
+}
+
+static int mc9s08dz60_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct mc9s08dz60 *mc9s;
+
+       mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL);
+       if (!mc9s)
+               return -ENOMEM;
+
+       mc9s->chip.label = client->name;
+       mc9s->chip.base = -1;
+       mc9s->chip.dev = &client->dev;
+       mc9s->chip.owner = THIS_MODULE;
+       mc9s->chip.ngpio = GPIO_NUM;
+       mc9s->chip.can_sleep = 1;
+       mc9s->chip.get = mc9s08dz60_get_value;
+       mc9s->chip.set = mc9s08dz60_set_value;
+       mc9s->chip.direction_output = mc9s08dz60_direction_output;
+       mc9s->client = client;
+       i2c_set_clientdata(client, mc9s);
+
+       ret = gpiochip_add(&mc9s->chip);
+       if (ret)
+               goto error;
+
+       return 0;
+
+ error:
+       kfree(mc9s);
+       return ret;
+}
+
+static int mc9s08dz60_remove(struct i2c_client *client)
+{
+       struct mc9s08dz60 *mc9s;
+       int ret;
+
+       mc9s = i2c_get_clientdata(client);
+
+       ret = gpiochip_remove(&mc9s->chip);
+       if (!ret)
+               kfree(mc9s);
+
+       return ret;
+
+}
+
+static const struct i2c_device_id mc9s08dz60_id[] = {
+       {"mc9s08dz60", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id);
+
+static struct i2c_driver mc9s08dz60_i2c_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "mc9s08dz60",
+       },
+       .probe = mc9s08dz60_probe,
+       .remove = mc9s08dz60_remove,
+       .id_table = mc9s08dz60_id,
+};
+
+module_i2c_driver(mc9s08dz60_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc. "
+               "Wu Guoxing <b39297@freescale.com>");
+MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board");
+MODULE_LICENSE("GPL v2");
index f49bd6f47a504b0ec732173e202f6f3dca716afd..1adc2ec1e3835ae98e230b160b63264eb0afb3bc 100644 (file)
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/irqdomain.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -50,10 +53,10 @@ struct gpio_regs {
 
 struct gpio_bank {
        struct list_head node;
-       unsigned long pbase;
        void __iomem *base;
        u16 irq;
-       u16 virtual_irq_start;
+       int irq_base;
+       struct irq_domain *domain;
        u32 suspend_wakeup;
        u32 saved_wakeup;
        u32 non_wakeup_gpios;
@@ -77,7 +80,6 @@ struct gpio_bank {
        int stride;
        u32 width;
        int context_loss_count;
-       u16 id;
        int power_mode;
        bool workaround_enabled;
 
@@ -91,6 +93,11 @@ struct gpio_bank {
 #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
 #define GPIO_MOD_CTRL_BIT      BIT(0)
 
+static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
+{
+       return gpio_irq - bank->irq_base + bank->chip.base;
+}
+
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
 {
        void __iomem *reg = bank->base;
@@ -113,10 +120,13 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
        void __iomem *reg = bank->base;
        u32 l = GPIO_BIT(bank, gpio);
 
-       if (enable)
+       if (enable) {
                reg += bank->regs->set_dataout;
-       else
+               bank->context.dataout |= l;
+       } else {
                reg += bank->regs->clr_dataout;
+               bank->context.dataout &= ~l;
+       }
 
        __raw_writel(l, reg);
 }
@@ -137,25 +147,25 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
        bank->context.dataout = l;
 }
 
-static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
+static int _get_gpio_datain(struct gpio_bank *bank, int offset)
 {
        void __iomem *reg = bank->base + bank->regs->datain;
 
-       return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+       return (__raw_readl(reg) & (1 << offset)) != 0;
 }
 
-static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
 {
        void __iomem *reg = bank->base + bank->regs->dataout;
 
-       return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+       return (__raw_readl(reg) & (1 << offset)) != 0;
 }
 
 static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
 {
        int l = __raw_readl(base + reg);
 
-       if (set) 
+       if (set)
                l |= mask;
        else
                l &= ~mask;
@@ -238,7 +248,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
 }
 
 static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
-                                               int trigger)
+                                               unsigned trigger)
 {
        void __iomem *base = bank->base;
        u32 gpio_bit = 1 << gpio;
@@ -320,7 +330,8 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
 static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
 #endif
 
-static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
+static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
+                                                       unsigned trigger)
 {
        void __iomem *reg = bank->base;
        void __iomem *base = bank->base;
@@ -367,7 +378,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
 
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
-       struct gpio_bank *bank;
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned gpio;
        int retval;
        unsigned long flags;
@@ -375,13 +386,11 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
        if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
                gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
        else
-               gpio = d->irq - IH_GPIO_BASE;
+               gpio = irq_to_gpio(bank, d->irq);
 
        if (type & ~IRQ_TYPE_SENSE_MASK)
                return -EINVAL;
 
-       bank = irq_data_get_irq_chip_data(d);
-
        if (!bank->regs->leveldetect0 &&
                (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
                return -EINVAL;
@@ -442,6 +451,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
        if (bank->regs->set_irqenable) {
                reg += bank->regs->set_irqenable;
                l = gpio_mask;
+               bank->context.irqenable1 |= gpio_mask;
        } else {
                reg += bank->regs->irqenable;
                l = __raw_readl(reg);
@@ -449,10 +459,10 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
                        l &= ~gpio_mask;
                else
                        l |= gpio_mask;
+               bank->context.irqenable1 = l;
        }
 
        __raw_writel(l, reg);
-       bank->context.irqenable1 = l;
 }
 
 static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
@@ -463,6 +473,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
        if (bank->regs->clr_irqenable) {
                reg += bank->regs->clr_irqenable;
                l = gpio_mask;
+               bank->context.irqenable1 &= ~gpio_mask;
        } else {
                reg += bank->regs->irqenable;
                l = __raw_readl(reg);
@@ -470,15 +481,18 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
                        l |= gpio_mask;
                else
                        l &= ~gpio_mask;
+               bank->context.irqenable1 = l;
        }
 
        __raw_writel(l, reg);
-       bank->context.irqenable1 = l;
 }
 
 static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
 {
-       _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+       if (enable)
+               _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+       else
+               _disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 /*
@@ -495,7 +509,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
        unsigned long flags;
 
        if (bank->non_wakeup_gpios & gpio_bit) {
-               dev_err(bank->dev, 
+               dev_err(bank->dev,
                        "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);
                return -EINVAL;
        }
@@ -506,6 +520,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
        else
                bank->suspend_wakeup &= ~gpio_bit;
 
+       __raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -522,14 +537,10 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank;
-       int retval;
-
-       bank = irq_data_get_irq_chip_data(d);
-       retval = _set_gpio_wakeup(bank, gpio, enable);
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
 
-       return retval;
+       return _set_gpio_wakeup(bank, gpio, enable);
 }
 
 static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -671,13 +682,15 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                if (!isr)
                        break;
 
-               gpio_irq = bank->virtual_irq_start;
+               gpio_irq = bank->irq_base;
                for (; isr != 0; isr >>= 1, gpio_irq++) {
-                       gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
+                       int gpio = irq_to_gpio(bank, gpio_irq);
 
                        if (!(isr & 1))
                                continue;
 
+                       gpio_index = GPIO_INDEX(bank, gpio);
+
                        /*
                         * Some chips can't respond to both rising and falling
                         * at the same time.  If this irq was requested with
@@ -703,8 +716,8 @@ exit:
 
 static void gpio_irq_shutdown(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
        unsigned long flags;
 
        spin_lock_irqsave(&bank->lock, flags);
@@ -714,16 +727,16 @@ static void gpio_irq_shutdown(struct irq_data *d)
 
 static void gpio_ack_irq(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
 
        _clear_gpio_irqstatus(bank, gpio);
 }
 
 static void gpio_mask_irq(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
        unsigned long flags;
 
        spin_lock_irqsave(&bank->lock, flags);
@@ -734,8 +747,8 @@ static void gpio_mask_irq(struct irq_data *d)
 
 static void gpio_unmask_irq(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
        unsigned int irq_mask = GPIO_BIT(bank, gpio);
        u32 trigger = irqd_get_trigger_type(d);
        unsigned long flags;
@@ -852,19 +865,15 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
 static int gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct gpio_bank *bank;
-       void __iomem *reg;
-       int gpio;
        u32 mask;
 
-       gpio = chip->base + offset;
        bank = container_of(chip, struct gpio_bank, chip);
-       reg = bank->base;
-       mask = GPIO_BIT(bank, gpio);
+       mask = (1 << offset);
 
        if (gpio_is_input(bank, mask))
-               return _get_gpio_datain(bank, gpio);
+               return _get_gpio_datain(bank, offset);
        else
-               return _get_gpio_dataout(bank, gpio);
+               return _get_gpio_dataout(bank, offset);
 }
 
 static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
@@ -917,7 +926,7 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
        struct gpio_bank *bank;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       return bank->virtual_irq_start + offset;
+       return bank->irq_base + offset;
 }
 
 /*---------------------------------------------------------------------*/
@@ -970,7 +979,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
                _gpio_rmw(base, bank->regs->ctrl, 0, 1);
 }
 
-static __init void
+static __devinit void
 omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
                    unsigned int num)
 {
@@ -1030,8 +1039,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 
        gpiochip_add(&bank->chip);
 
-       for (j = bank->virtual_irq_start;
-                    j < bank->virtual_irq_start + bank->width; j++) {
+       for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) {
                irq_set_lockdep_class(j, &gpio_lock_class);
                irq_set_chip_data(j, bank);
                if (bank->is_mpuio) {
@@ -1046,39 +1054,38 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
        irq_set_handler_data(bank->irq, bank);
 }
 
+static const struct of_device_id omap_gpio_match[];
+
 static int __devinit omap_gpio_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       const struct of_device_id *match;
        struct omap_gpio_platform_data *pdata;
        struct resource *res;
        struct gpio_bank *bank;
        int ret = 0;
 
-       if (!pdev->dev.platform_data) {
-               ret = -EINVAL;
-               goto err_exit;
-       }
+       match = of_match_device(of_match_ptr(omap_gpio_match), dev);
+
+       pdata = match ? match->data : dev->platform_data;
+       if (!pdata)
+               return -EINVAL;
 
-       bank = kzalloc(sizeof(struct gpio_bank), GFP_KERNEL);
+       bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
        if (!bank) {
-               dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
-               ret = -ENOMEM;
-               goto err_exit;
+               dev_err(dev, "Memory alloc failed\n");
+               return -ENOMEM;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (unlikely(!res)) {
-               dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n",
-                               pdev->id);
-               ret = -ENODEV;
-               goto err_free;
+               dev_err(dev, "Invalid IRQ resource\n");
+               return -ENODEV;
        }
 
        bank->irq = res->start;
-       bank->id = pdev->id;
-
-       pdata = pdev->dev.platform_data;
-       bank->virtual_irq_start = pdata->virtual_irq_start;
-       bank->dev = &pdev->dev;
+       bank->dev = dev;
        bank->dbck_flag = pdata->dbck_flag;
        bank->stride = pdata->bank_stride;
        bank->width = pdata->bank_width;
@@ -1087,6 +1094,18 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        bank->loses_context = pdata->loses_context;
        bank->get_context_loss_count = pdata->get_context_loss_count;
        bank->regs = pdata->regs;
+#ifdef CONFIG_OF_GPIO
+       bank->chip.of_node = of_node_get(node);
+#endif
+
+       bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+       if (bank->irq_base < 0) {
+               dev_err(dev, "Couldn't allocate IRQ numbers\n");
+               return -ENODEV;
+       }
+
+       bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base,
+                                            0, &irq_domain_simple_ops, NULL);
 
        if (bank->regs->set_dataout && bank->regs->clr_dataout)
                bank->set_dataout = _set_gpio_dataout_reg;
@@ -1098,18 +1117,20 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        /* Static mapping, never released */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!res)) {
-               dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n",
-                               pdev->id);
-               ret = -ENODEV;
-               goto err_free;
+               dev_err(dev, "Invalid mem resource\n");
+               return -ENODEV;
        }
 
-       bank->base = ioremap(res->start, resource_size(res));
+       if (!devm_request_mem_region(dev, res->start, resource_size(res),
+                                    pdev->name)) {
+               dev_err(dev, "Region already claimed\n");
+               return -EBUSY;
+       }
+
+       bank->base = devm_ioremap(dev, res->start, resource_size(res));
        if (!bank->base) {
-               dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n",
-                               pdev->id);
-               ret = -ENOMEM;
-               goto err_free;
+               dev_err(dev, "Could not ioremap\n");
+               return -ENOMEM;
        }
 
        platform_set_drvdata(pdev, bank);
@@ -1130,11 +1151,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        list_add_tail(&bank->node, &omap_gpio_list);
 
        return ret;
-
-err_free:
-       kfree(bank);
-err_exit:
-       return ret;
 }
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
@@ -1196,8 +1212,30 @@ static int omap_gpio_runtime_suspend(struct device *dev)
        struct gpio_bank *bank = platform_get_drvdata(pdev);
        u32 l1 = 0, l2 = 0;
        unsigned long flags;
+       u32 wake_low, wake_hi;
 
        spin_lock_irqsave(&bank->lock, flags);
+
+       /*
+        * Only edges can generate a wakeup event to the PRCM.
+        *
+        * Therefore, ensure any wake-up capable GPIOs have
+        * edge-detection enabled before going idle to ensure a wakeup
+        * to the PRCM is generated on a GPIO transition. (c.f. 34xx
+        * NDA TRM 25.5.3.1)
+        *
+        * The normal values will be restored upon ->runtime_resume()
+        * by writing back the values saved in bank->context.
+        */
+       wake_low = bank->context.leveldetect0 & bank->context.wake_en;
+       if (wake_low)
+               __raw_writel(wake_low | bank->context.fallingdetect,
+                            bank->base + bank->regs->fallingdetect);
+       wake_hi = bank->context.leveldetect1 & bank->context.wake_en;
+       if (wake_hi)
+               __raw_writel(wake_hi | bank->context.risingdetect,
+                            bank->base + bank->regs->risingdetect);
+
        if (bank->power_mode != OFF_MODE) {
                bank->power_mode = 0;
                goto update_gpio_context_count;
@@ -1207,9 +1245,6 @@ static int omap_gpio_runtime_suspend(struct device *dev)
         * non-wakeup GPIOs.  Otherwise spurious IRQs will be
         * generated.  See OMAP2420 Errata item 1.101.
         */
-       if (!(bank->enabled_non_wakeup_gpios))
-               goto update_gpio_context_count;
-
        bank->saved_datain = __raw_readl(bank->base +
                                                bank->regs->datain);
        l1 = __raw_readl(bank->base + bank->regs->fallingdetect);
@@ -1246,7 +1281,19 @@ static int omap_gpio_runtime_resume(struct device *dev)
 
        spin_lock_irqsave(&bank->lock, flags);
        _gpio_dbck_enable(bank);
-       if (!bank->enabled_non_wakeup_gpios || !bank->workaround_enabled) {
+
+       /*
+        * In ->runtime_suspend(), level-triggered, wakeup-enabled
+        * GPIOs were set to edge trigger also in order to be able to
+        * generate a PRCM wakeup.  Here we restore the
+        * pre-runtime_suspend() values for edge triggering.
+        */
+       __raw_writel(bank->context.fallingdetect,
+                    bank->base + bank->regs->fallingdetect);
+       __raw_writel(bank->context.risingdetect,
+                    bank->base + bank->regs->risingdetect);
+
+       if (!bank->workaround_enabled) {
                spin_unlock_irqrestore(&bank->lock, flags);
                return 0;
        }
@@ -1397,11 +1444,95 @@ static const struct dev_pm_ops gpio_pm_ops = {
                                                                        NULL)
 };
 
+#if defined(CONFIG_OF)
+static struct omap_gpio_reg_offs omap2_gpio_regs = {
+       .revision =             OMAP24XX_GPIO_REVISION,
+       .direction =            OMAP24XX_GPIO_OE,
+       .datain =               OMAP24XX_GPIO_DATAIN,
+       .dataout =              OMAP24XX_GPIO_DATAOUT,
+       .set_dataout =          OMAP24XX_GPIO_SETDATAOUT,
+       .clr_dataout =          OMAP24XX_GPIO_CLEARDATAOUT,
+       .irqstatus =            OMAP24XX_GPIO_IRQSTATUS1,
+       .irqstatus2 =           OMAP24XX_GPIO_IRQSTATUS2,
+       .irqenable =            OMAP24XX_GPIO_IRQENABLE1,
+       .irqenable2 =           OMAP24XX_GPIO_IRQENABLE2,
+       .set_irqenable =        OMAP24XX_GPIO_SETIRQENABLE1,
+       .clr_irqenable =        OMAP24XX_GPIO_CLEARIRQENABLE1,
+       .debounce =             OMAP24XX_GPIO_DEBOUNCE_VAL,
+       .debounce_en =          OMAP24XX_GPIO_DEBOUNCE_EN,
+       .ctrl =                 OMAP24XX_GPIO_CTRL,
+       .wkup_en =              OMAP24XX_GPIO_WAKE_EN,
+       .leveldetect0 =         OMAP24XX_GPIO_LEVELDETECT0,
+       .leveldetect1 =         OMAP24XX_GPIO_LEVELDETECT1,
+       .risingdetect =         OMAP24XX_GPIO_RISINGDETECT,
+       .fallingdetect =        OMAP24XX_GPIO_FALLINGDETECT,
+};
+
+static struct omap_gpio_reg_offs omap4_gpio_regs = {
+       .revision =             OMAP4_GPIO_REVISION,
+       .direction =            OMAP4_GPIO_OE,
+       .datain =               OMAP4_GPIO_DATAIN,
+       .dataout =              OMAP4_GPIO_DATAOUT,
+       .set_dataout =          OMAP4_GPIO_SETDATAOUT,
+       .clr_dataout =          OMAP4_GPIO_CLEARDATAOUT,
+       .irqstatus =            OMAP4_GPIO_IRQSTATUS0,
+       .irqstatus2 =           OMAP4_GPIO_IRQSTATUS1,
+       .irqenable =            OMAP4_GPIO_IRQSTATUSSET0,
+       .irqenable2 =           OMAP4_GPIO_IRQSTATUSSET1,
+       .set_irqenable =        OMAP4_GPIO_IRQSTATUSSET0,
+       .clr_irqenable =        OMAP4_GPIO_IRQSTATUSCLR0,
+       .debounce =             OMAP4_GPIO_DEBOUNCINGTIME,
+       .debounce_en =          OMAP4_GPIO_DEBOUNCENABLE,
+       .ctrl =                 OMAP4_GPIO_CTRL,
+       .wkup_en =              OMAP4_GPIO_IRQWAKEN0,
+       .leveldetect0 =         OMAP4_GPIO_LEVELDETECT0,
+       .leveldetect1 =         OMAP4_GPIO_LEVELDETECT1,
+       .risingdetect =         OMAP4_GPIO_RISINGDETECT,
+       .fallingdetect =        OMAP4_GPIO_FALLINGDETECT,
+};
+
+static struct omap_gpio_platform_data omap2_pdata = {
+       .regs = &omap2_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = false,
+};
+
+static struct omap_gpio_platform_data omap3_pdata = {
+       .regs = &omap2_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = true,
+};
+
+static struct omap_gpio_platform_data omap4_pdata = {
+       .regs = &omap4_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = true,
+};
+
+static const struct of_device_id omap_gpio_match[] = {
+       {
+               .compatible = "ti,omap4-gpio",
+               .data = &omap4_pdata,
+       },
+       {
+               .compatible = "ti,omap3-gpio",
+               .data = &omap3_pdata,
+       },
+       {
+               .compatible = "ti,omap2-gpio",
+               .data = &omap2_pdata,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, omap_gpio_match);
+#endif
+
 static struct platform_driver omap_gpio_driver = {
        .probe          = omap_gpio_probe,
        .driver         = {
                .name   = "omap_gpio",
                .pm     = &gpio_pm_ops,
+               .of_match_table = of_match_ptr(omap_gpio_match),
        },
 };
 
index 77c9cc70fa7753fb406b87dbbf201021b4b6eb18..b4b5da4fd2cc896f219859bc9849831c2c0527c4 100644 (file)
@@ -352,7 +352,12 @@ static int pl061_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume);
+static const struct dev_pm_ops pl061_dev_pm_ops = {
+       .suspend = pl061_suspend,
+       .resume = pl061_resume,
+       .freeze = pl061_suspend,
+       .restore = pl061_resume,
+};
 #endif
 
 static struct amba_id pl061_ids[] = {
index b2d3ee1d183a50b2da33ac819d2a74375966b726..5689ce62fd81badc2fdeceeb604fdf866d5b3bda 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
+#include <mach/irqs.h>
+
 /*
  * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
  * one set of registers. The register offsets are organized below:
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
new file mode 100644 (file)
index 0000000..9ba15d3
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ *  GPIO interface for Intel Sodaville SoCs.
+ *
+ *  Copyright (c) 2010, 2011 Intel Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/basic_mmio_gpio.h>
+
+#define DRV_NAME               "sdv_gpio"
+#define SDV_NUM_PUB_GPIOS      12
+#define PCI_DEVICE_ID_SDV_GPIO 0x2e67
+#define GPIO_BAR               0
+
+#define GPOUTR         0x00
+#define GPOER          0x04
+#define GPINR          0x08
+
+#define GPSTR          0x0c
+#define GPIT1R0                0x10
+#define GPIO_INT       0x14
+#define GPIT1R1                0x18
+
+#define GPMUXCTL       0x1c
+
+struct sdv_gpio_chip_data {
+       int irq_base;
+       void __iomem *gpio_pub_base;
+       struct irq_domain id;
+       struct irq_chip_generic *gc;
+       struct bgpio_chip bgpio;
+};
+
+static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct sdv_gpio_chip_data *sd = gc->private;
+       void __iomem *type_reg;
+       u32 irq_offs = d->irq - sd->irq_base;
+       u32 reg;
+
+       if (irq_offs < 8)
+               type_reg = sd->gpio_pub_base + GPIT1R0;
+       else
+               type_reg = sd->gpio_pub_base + GPIT1R1;
+
+       reg = readl(type_reg);
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_HIGH:
+               reg &= ~BIT(4 * (irq_offs % 8));
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               reg |= BIT(4 * (irq_offs % 8));
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       writel(reg, type_reg);
+       return 0;
+}
+
+static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data)
+{
+       struct sdv_gpio_chip_data *sd = data;
+       u32 irq_stat = readl(sd->gpio_pub_base + GPSTR);
+
+       irq_stat &= readl(sd->gpio_pub_base + GPIO_INT);
+       if (!irq_stat)
+               return IRQ_NONE;
+
+       while (irq_stat) {
+               u32 irq_bit = __fls(irq_stat);
+
+               irq_stat &= ~BIT(irq_bit);
+               generic_handle_irq(sd->irq_base + irq_bit);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int sdv_xlate(struct irq_domain *h, struct device_node *node,
+               const u32 *intspec, u32 intsize, irq_hw_number_t *out_hwirq,
+               u32 *out_type)
+{
+       u32 line, type;
+
+       if (node != h->of_node)
+               return -EINVAL;
+
+       if (intsize < 2)
+               return -EINVAL;
+
+       line = *intspec;
+       *out_hwirq = line;
+
+       intspec++;
+       type = *intspec;
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_LOW:
+       case IRQ_TYPE_LEVEL_HIGH:
+               *out_type = type;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static struct irq_domain_ops irq_domain_sdv_ops = {
+       .dt_translate   = sdv_xlate,
+};
+
+static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+               struct pci_dev *pdev)
+{
+       struct irq_chip_type *ct;
+       int ret;
+
+       sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1);
+       if (sd->irq_base < 0)
+               return sd->irq_base;
+
+       /* mask + ACK all interrupt sources */
+       writel(0, sd->gpio_pub_base + GPIO_INT);
+       writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR);
+
+       ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED,
+                       "sdv_gpio", sd);
+       if (ret)
+               goto out_free_desc;
+
+       sd->id.irq_base = sd->irq_base;
+       sd->id.of_node = of_node_get(pdev->dev.of_node);
+       sd->id.ops = &irq_domain_sdv_ops;
+
+       /*
+        * This gpio irq controller latches level irqs. Testing shows that if
+        * we unmask & ACK the IRQ before the source of the interrupt is gone
+        * then the interrupt is active again.
+        */
+       sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base,
+                       sd->gpio_pub_base, handle_fasteoi_irq);
+       if (!sd->gc) {
+               ret = -ENOMEM;
+               goto out_free_irq;
+       }
+
+       sd->gc->private = sd;
+       ct = sd->gc->chip_types;
+       ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+       ct->regs.eoi = GPSTR;
+       ct->regs.mask = GPIO_INT;
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       ct->chip.irq_eoi = irq_gc_eoi;
+       ct->chip.irq_set_type = sdv_gpio_pub_set_type;
+
+       irq_setup_generic_chip(sd->gc, IRQ_MSK(SDV_NUM_PUB_GPIOS),
+                       IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST,
+                       IRQ_LEVEL | IRQ_NOPROBE);
+
+       irq_domain_add(&sd->id);
+       return 0;
+out_free_irq:
+       free_irq(pdev->irq, sd);
+out_free_desc:
+       irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
+       return ret;
+}
+
+static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
+                                       const struct pci_device_id *pci_id)
+{
+       struct sdv_gpio_chip_data *sd;
+       unsigned long addr;
+       const void *prop;
+       int len;
+       int ret;
+       u32 mux_val;
+
+       sd = kzalloc(sizeof(struct sdv_gpio_chip_data), GFP_KERNEL);
+       if (!sd)
+               return -ENOMEM;
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "can't enable device.\n");
+               goto done;
+       }
+
+       ret = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
+       if (ret) {
+               dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
+               goto disable_pci;
+       }
+
+       addr = pci_resource_start(pdev, GPIO_BAR);
+       if (!addr)
+               goto release_reg;
+       sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR));
+
+       prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len);
+       if (prop && len == 4) {
+               mux_val = of_read_number(prop, 1);
+               writel(mux_val, sd->gpio_pub_base + GPMUXCTL);
+       }
+
+       ret = bgpio_init(&sd->bgpio, &pdev->dev, 4,
+                       sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR,
+                       NULL, sd->gpio_pub_base + GPOER, NULL, false);
+       if (ret)
+               goto unmap;
+       sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS;
+
+       ret = gpiochip_add(&sd->bgpio.gc);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "gpiochip_add() failed.\n");
+               goto unmap;
+       }
+
+       ret = sdv_register_irqsupport(sd, pdev);
+       if (ret)
+               goto unmap;
+
+       pci_set_drvdata(pdev, sd);
+       dev_info(&pdev->dev, "Sodaville GPIO driver registered.\n");
+       return 0;
+
+unmap:
+       iounmap(sd->gpio_pub_base);
+release_reg:
+       pci_release_region(pdev, GPIO_BAR);
+disable_pci:
+       pci_disable_device(pdev);
+done:
+       kfree(sd);
+       return ret;
+}
+
+static void sdv_gpio_remove(struct pci_dev *pdev)
+{
+       struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev);
+
+       irq_domain_del(&sd->id);
+       free_irq(pdev->irq, sd);
+       irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
+
+       if (gpiochip_remove(&sd->bgpio.gc))
+               dev_err(&pdev->dev, "gpiochip_remove() failed.\n");
+
+       pci_release_region(pdev, GPIO_BAR);
+       iounmap(sd->gpio_pub_base);
+       pci_disable_device(pdev);
+       kfree(sd);
+}
+
+static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) },
+       { 0, },
+};
+
+static struct pci_driver sdv_gpio_driver = {
+       .name = DRV_NAME,
+       .id_table = sdv_gpio_pci_ids,
+       .probe = sdv_gpio_probe,
+       .remove = sdv_gpio_remove,
+};
+
+static int __init sdv_gpio_init(void)
+{
+       return pci_register_driver(&sdv_gpio_driver);
+}
+module_init(sdv_gpio_init);
+
+static void __exit sdv_gpio_exit(void)
+{
+       pci_unregister_driver(&sdv_gpio_driver);
+}
+module_exit(sdv_gpio_exit);
+
+MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>");
+MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs");
+MODULE_LICENSE("GPL v2");
index 87a68a896abf7a0a010aa6395db5b0a53ba9ba41..dce34727bbf8774895e471ca32b6a025842c99ee 100644 (file)
@@ -54,7 +54,7 @@ static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
        if (ret < 0)
                return ret;
 
-       return ret & mask;
+       return !!(ret & mask);
 }
 
 static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
@@ -307,13 +307,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
        struct stmpe_gpio_platform_data *pdata;
        struct stmpe_gpio *stmpe_gpio;
        int ret;
-       int irq;
+       int irq = 0;
 
        pdata = stmpe->pdata->gpio;
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
 
        stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
        if (!stmpe_gpio)
@@ -330,21 +328,28 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
        stmpe_gpio->chip.dev = &pdev->dev;
        stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
-       stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
+       if (irq >= 0)
+               stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
+       else
+               dev_info(&pdev->dev,
+                       "device configured in no-irq mode; "
+                       "irqs are not available\n");
 
        ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
        if (ret)
                goto out_free;
 
-       ret = stmpe_gpio_irq_init(stmpe_gpio);
-       if (ret)
-               goto out_disable;
+       if (irq >= 0) {
+               ret = stmpe_gpio_irq_init(stmpe_gpio);
+               if (ret)
+                       goto out_disable;
 
-       ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT,
-                                  "stmpe-gpio", stmpe_gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-               goto out_removeirq;
+               ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq,
+                               IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+                       goto out_removeirq;
+               }
        }
 
        ret = gpiochip_add(&stmpe_gpio->chip);
@@ -361,9 +366,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
        return 0;
 
 out_freeirq:
-       free_irq(irq, stmpe_gpio);
+       if (irq >= 0)
+               free_irq(irq, stmpe_gpio);
 out_removeirq:
-       stmpe_gpio_irq_remove(stmpe_gpio);
+       if (irq >= 0)
+               stmpe_gpio_irq_remove(stmpe_gpio);
 out_disable:
        stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 out_free:
@@ -391,8 +398,10 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
 
        stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 
-       free_irq(irq, stmpe_gpio);
-       stmpe_gpio_irq_remove(stmpe_gpio);
+       if (irq >= 0) {
+               free_irq(irq, stmpe_gpio);
+               stmpe_gpio_irq_remove(stmpe_gpio);
+       }
        platform_set_drvdata(pdev, NULL);
        kfree(stmpe_gpio);
 
index 6f17671260e17b94d8176befe18e6706eb228832..32de6707e3c456a19750e33dd21923bde2fcd41e 100644 (file)
@@ -109,11 +109,13 @@ void tegra_gpio_enable(int gpio)
 {
        tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
 }
+EXPORT_SYMBOL_GPL(tegra_gpio_enable);
 
 void tegra_gpio_disable(int gpio)
 {
        tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
 }
+EXPORT_SYMBOL_GPL(tegra_gpio_disable);
 
 static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
@@ -459,7 +461,7 @@ static int __init tegra_gpio_init(void)
 }
 postcore_initcall(tegra_gpio_init);
 
-void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
+void tegra_gpio_config(struct tegra_gpio_table *table, int num)
 {
        int i;
 
index 91f45b965d1e812d542e81d2c81ab6e60ae52843..7eef648a3351a2b89e1de03f95f168b8889f8634 100644 (file)
@@ -69,6 +69,7 @@ static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
 void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
 {
        int ret;
+       struct tps65910_board *board_data;
 
        if (!gpio_base)
                return;
@@ -80,10 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
 
        switch(tps65910_chip_id(tps65910)) {
        case TPS65910:
-               tps65910->gpio.ngpio    = 6;
+               tps65910->gpio.ngpio    = TPS65910_NUM_GPIO;
                break;
        case TPS65911:
-               tps65910->gpio.ngpio    = 9;
+               tps65910->gpio.ngpio    = TPS65911_NUM_GPIO;
                break;
        default:
                return;
@@ -95,6 +96,21 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
        tps65910->gpio.set              = tps65910_gpio_set;
        tps65910->gpio.get              = tps65910_gpio_get;
 
+       /* Configure sleep control for gpios */
+       board_data = dev_get_platdata(tps65910->dev);
+       if (board_data) {
+               int i;
+               for (i = 0; i < tps65910->gpio.ngpio; ++i) {
+                       if (board_data->en_gpio_sleep[i]) {
+                               ret = tps65910_set_bits(tps65910,
+                                       TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
+                               if (ret < 0)
+                                       dev_warn(tps65910->dev,
+                                               "GPIO Sleep setting failed\n");
+                       }
+               }
+       }
+
        ret = gpiochip_add(&tps65910->gpio);
 
        if (ret)
index b8b4f228757c8777aca6554f39fcd7a05255f3be..94256fe7bf36de35556421d2a1d04ace98b3e59c 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 
 #include <linux/i2c/twl.h>
 
@@ -256,7 +258,8 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
                 * and vMMC2 power supplies based on card presence.
                 */
                pdata = chip->dev->platform_data;
-               value |= pdata->mmc_cd & 0x03;
+               if (pdata)
+                       value |= pdata->mmc_cd & 0x03;
 
                status = gpio_twl4030_write(REG_GPIO_CTRL, value);
        }
@@ -395,59 +398,70 @@ static int gpio_twl4030_remove(struct platform_device *pdev);
 static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
 {
        struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
-       int ret;
+       struct device_node *node = pdev->dev.of_node;
+       int ret, irq_base;
 
        /* maybe setup IRQs */
-       if (pdata->irq_base) {
-               if (is_module()) {
-                       dev_err(&pdev->dev,
-                               "can't dispatch IRQs from modules\n");
-                       goto no_irqs;
-               }
-               ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
-               if (ret < 0)
-                       return ret;
-               WARN_ON(ret != pdata->irq_base);
-               twl4030_gpio_irq_base = ret;
+       if (is_module()) {
+               dev_err(&pdev->dev, "can't dispatch IRQs from modules\n");
+               goto no_irqs;
+       }
+
+       irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0);
+       if (irq_base < 0) {
+               dev_err(&pdev->dev, "Failed to alloc irq_descs\n");
+               return irq_base;
        }
 
+       irq_domain_add_legacy(node, TWL4030_GPIO_MAX, irq_base, 0,
+                             &irq_domain_simple_ops, NULL);
+
+       ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base);
+       if (ret < 0)
+               return ret;
+
+       twl4030_gpio_irq_base = irq_base;
+
 no_irqs:
-       /*
-        * NOTE:  boards may waste power if they don't set pullups
-        * and pulldowns correctly ... default for non-ULPI pins is
-        * pulldown, and some other pins may have external pullups
-        * or pulldowns.  Careful!
-        */
-       ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
-       if (ret)
-               dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
-                               pdata->pullups, pdata->pulldowns,
-                               ret);
-
-       ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
-       if (ret)
-               dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
-                               pdata->debounce, pdata->mmc_cd,
-                               ret);
-
-       twl_gpiochip.base = pdata->gpio_base;
+       twl_gpiochip.base = -1;
        twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
        twl_gpiochip.dev = &pdev->dev;
 
-       /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
-        * is (still) clear if use_leds is set.
-        */
-       if (pdata->use_leds)
-               twl_gpiochip.ngpio += 2;
+       if (pdata) {
+               twl_gpiochip.base = pdata->gpio_base;
+
+               /*
+                * NOTE:  boards may waste power if they don't set pullups
+                * and pulldowns correctly ... default for non-ULPI pins is
+                * pulldown, and some other pins may have external pullups
+                * or pulldowns.  Careful!
+                */
+               ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+               if (ret)
+                       dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+                                       pdata->pullups, pdata->pulldowns,
+                                       ret);
+
+               ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+               if (ret)
+                       dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+                                       pdata->debounce, pdata->mmc_cd,
+                                       ret);
+
+               /*
+                * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+                * is (still) clear if use_leds is set.
+                */
+               if (pdata->use_leds)
+                       twl_gpiochip.ngpio += 2;
+       }
 
        ret = gpiochip_add(&twl_gpiochip);
        if (ret < 0) {
-               dev_err(&pdev->dev,
-                               "could not register gpiochip, %d\n",
-                               ret);
+               dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
                twl_gpiochip.ngpio = 0;
                gpio_twl4030_remove(pdev);
-       } else if (pdata->setup) {
+       } else if (pdata && pdata->setup) {
                int status;
 
                status = pdata->setup(&pdev->dev,
@@ -465,7 +479,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
        struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
        int status;
 
-       if (pdata->teardown) {
+       if (pdata && pdata->teardown) {
                status = pdata->teardown(&pdev->dev,
                                pdata->gpio_base, TWL4030_GPIO_MAX);
                if (status) {
@@ -486,12 +500,21 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
        return -EIO;
 }
 
+static const struct of_device_id twl_gpio_match[] = {
+       { .compatible = "ti,twl4030-gpio", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl_gpio_match);
+
 /* Note:  this hardware lives inside an I2C-based multi-function device. */
 MODULE_ALIAS("platform:twl4030_gpio");
 
 static struct platform_driver gpio_twl4030_driver = {
-       .driver.name    = "twl4030_gpio",
-       .driver.owner   = THIS_MODULE,
+       .driver = {
+               .name   = "twl4030_gpio",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(twl_gpio_match),
+       },
        .probe          = gpio_twl4030_probe,
        .remove         = gpio_twl4030_remove,
 };
index 17fdf4b6af93147428166e6ea595987b2ac59d02..5a75510d66bb14a2148c71432104fc7ac5f39d9b 100644 (file)
@@ -58,6 +58,8 @@ struct gpio_desc {
 #define FLAG_TRIG_FALL 5       /* trigger on falling edge */
 #define FLAG_TRIG_RISE 6       /* trigger on rising edge */
 #define FLAG_ACTIVE_LOW        7       /* sysfs value has active low */
+#define FLAG_OPEN_DRAIN        8       /* Gpio is open drain type */
+#define FLAG_OPEN_SOURCE 9     /* Gpio is open source type */
 
 #define ID_SHIFT       16      /* add new flags before this one */
 
@@ -873,6 +875,7 @@ void gpio_unexport(unsigned gpio)
 {
        struct gpio_desc        *desc;
        int                     status = 0;
+       struct device           *dev = NULL;
 
        if (!gpio_is_valid(gpio)) {
                status = -EINVAL;
@@ -884,19 +887,20 @@ void gpio_unexport(unsigned gpio)
        desc = &gpio_desc[gpio];
 
        if (test_bit(FLAG_EXPORT, &desc->flags)) {
-               struct device   *dev = NULL;
 
                dev = class_find_device(&gpio_class, NULL, desc, match_export);
                if (dev) {
                        gpio_setup_irq(desc, dev, 0);
                        clear_bit(FLAG_EXPORT, &desc->flags);
-                       put_device(dev);
-                       device_unregister(dev);
                } else
                        status = -ENODEV;
        }
 
        mutex_unlock(&sysfs_lock);
+       if (dev) {
+               device_unregister(dev);
+               put_device(dev);
+       }
 done:
        if (status)
                pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
@@ -1150,8 +1154,9 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
  * non-zero, this function will return to the caller and not iterate over any
  * more gpio_chips.
  */
-struct gpio_chip *gpiochip_find(void *data,
-                               int (*match)(struct gpio_chip *chip, void *data))
+struct gpio_chip *gpiochip_find(const void *data,
+                               int (*match)(struct gpio_chip *chip,
+                                            const void *data))
 {
        struct gpio_chip *chip = NULL;
        unsigned long flags;
@@ -1261,6 +1266,8 @@ void gpio_free(unsigned gpio)
                module_put(desc->chip->owner);
                clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
                clear_bit(FLAG_REQUESTED, &desc->flags);
+               clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
+               clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
        } else
                WARN_ON(extra_checks);
 
@@ -1282,6 +1289,12 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
        if (err)
                return err;
 
+       if (flags & GPIOF_OPEN_DRAIN)
+               set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags);
+
+       if (flags & GPIOF_OPEN_SOURCE)
+               set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags);
+
        if (flags & GPIOF_DIR_IN)
                err = gpio_direction_input(gpio);
        else
@@ -1431,6 +1444,14 @@ int gpio_direction_output(unsigned gpio, int value)
        struct gpio_desc        *desc = &gpio_desc[gpio];
        int                     status = -EINVAL;
 
+       /* Open drain pin should not be driven to 1 */
+       if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
+               return gpio_direction_input(gpio);
+
+       /* Open source pin should not be driven to 0 */
+       if (!value && test_bit(FLAG_OPEN_SOURCE,  &desc->flags))
+               return gpio_direction_input(gpio);
+
        spin_lock_irqsave(&gpio_lock, flags);
 
        if (!gpio_is_valid(gpio))
@@ -1560,6 +1581,7 @@ int __gpio_get_value(unsigned gpio)
        int value;
 
        chip = gpio_to_chip(gpio);
+       /* Should be using gpio_get_value_cansleep() */
        WARN_ON(chip->can_sleep);
        value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
        trace_gpio_value(gpio, 1, value);
@@ -1567,6 +1589,57 @@ int __gpio_get_value(unsigned gpio)
 }
 EXPORT_SYMBOL_GPL(__gpio_get_value);
 
+/*
+ *  _gpio_set_open_drain_value() - Set the open drain gpio's value.
+ * @gpio: Gpio whose state need to be set.
+ * @chip: Gpio chip.
+ * @value: Non-zero for setting it HIGH otherise it will set to LOW.
+ */
+static void _gpio_set_open_drain_value(unsigned gpio,
+                       struct gpio_chip *chip, int value)
+{
+       int err = 0;
+       if (value) {
+               err = chip->direction_input(chip, gpio - chip->base);
+               if (!err)
+                       clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       } else {
+               err = chip->direction_output(chip, gpio - chip->base, 0);
+               if (!err)
+                       set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       }
+       trace_gpio_direction(gpio, value, err);
+       if (err < 0)
+               pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
+                                       __func__, gpio, err);
+}
+
+/*
+ *  _gpio_set_open_source() - Set the open source gpio's value.
+ * @gpio: Gpio whose state need to be set.
+ * @chip: Gpio chip.
+ * @value: Non-zero for setting it HIGH otherise it will set to LOW.
+ */
+static void _gpio_set_open_source_value(unsigned gpio,
+                       struct gpio_chip *chip, int value)
+{
+       int err = 0;
+       if (value) {
+               err = chip->direction_output(chip, gpio - chip->base, 1);
+               if (!err)
+                       set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       } else {
+               err = chip->direction_input(chip, gpio - chip->base);
+               if (!err)
+                       clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       }
+       trace_gpio_direction(gpio, !value, err);
+       if (err < 0)
+               pr_err("%s: Error in set_value for open source gpio%d err %d\n",
+                                       __func__, gpio, err);
+}
+
+
 /**
  * __gpio_set_value() - assign a gpio's value
  * @gpio: gpio whose value will be assigned
@@ -1581,9 +1654,15 @@ void __gpio_set_value(unsigned gpio, int value)
        struct gpio_chip        *chip;
 
        chip = gpio_to_chip(gpio);
+       /* Should be using gpio_set_value_cansleep() */
        WARN_ON(chip->can_sleep);
        trace_gpio_value(gpio, 0, value);
-       chip->set(chip, gpio - chip->base, value);
+       if (test_bit(FLAG_OPEN_DRAIN,  &gpio_desc[gpio].flags))
+               _gpio_set_open_drain_value(gpio, chip, value);
+       else if (test_bit(FLAG_OPEN_SOURCE,  &gpio_desc[gpio].flags))
+               _gpio_set_open_source_value(gpio, chip, value);
+       else
+               chip->set(chip, gpio - chip->base, value);
 }
 EXPORT_SYMBOL_GPL(__gpio_set_value);
 
@@ -1650,7 +1729,12 @@ void gpio_set_value_cansleep(unsigned gpio, int value)
        might_sleep_if(extra_checks);
        chip = gpio_to_chip(gpio);
        trace_gpio_value(gpio, 0, value);
-       chip->set(chip, gpio - chip->base, value);
+       if (test_bit(FLAG_OPEN_DRAIN,  &gpio_desc[gpio].flags))
+               _gpio_set_open_drain_value(gpio, chip, value);
+       else if (test_bit(FLAG_OPEN_SOURCE,  &gpio_desc[gpio].flags))
+               _gpio_set_open_source_value(gpio, chip, value);
+       else
+               chip->set(chip, gpio - chip->base, value);
 }
 EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
 
index 4c2cb4a8ad985624f1e706cbc0b4ae7f29652fd6..5675d93b420567b3c3c5f2730c915434da9be21a 100644 (file)
@@ -244,7 +244,6 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
                                uint64_t value)
 {
        struct drm_encoder *encoder = connector->encoder;
-       struct backlight_device *psb_bd;
 
        if (!strcmp(property->name, "scaling mode") && encoder) {
                struct psb_intel_crtc *psb_crtc =
@@ -301,11 +300,15 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
                                                                        value))
                        goto set_prop_error;
                else {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+                       struct backlight_device *psb_bd;
+
                        psb_bd = mdfld_get_backlight_device();
                        if (psb_bd) {
                                psb_bd->props.brightness = value;
                                mdfld_set_brightness(psb_bd);
                        }
+#endif
                }
        }
 set_prop_done:
index 0694e170a338932ca7f81fa3559e0bf615076949..1a7559b59997cfaa8782e898e7c39cce09465f02 100644 (file)
@@ -467,6 +467,10 @@ static int i915_drm_freeze(struct drm_device *dev)
        /* Modeset on resume, not lid events */
        dev_priv->modeset_on_lid = 0;
 
+       console_lock();
+       intel_fbdev_set_suspend(dev, 1);
+       console_unlock();
+
        return 0;
 }
 
@@ -539,6 +543,9 @@ static int i915_drm_thaw(struct drm_device *dev)
 
        dev_priv->modeset_on_lid = 0;
 
+       console_lock();
+       intel_fbdev_set_suspend(dev, 0);
+       console_unlock();
        return error;
 }
 
index 9cec6c3937faef852f036ee5134cec067367e52d..5a14149b3794237ad26ee24bce00b5938e157b93 100644 (file)
@@ -382,7 +382,7 @@ extern int intel_framebuffer_init(struct drm_device *dev,
                                  struct drm_i915_gem_object *obj);
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_fini(struct drm_device *dev);
-
+extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);
 extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
 extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
 extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
index 2d8766978388d43316263fa542a31971b078b176..19ecd78b8a2ce572c98b1407122e1d97d94c4781 100644 (file)
@@ -254,6 +254,16 @@ void intel_fbdev_fini(struct drm_device *dev)
        kfree(dev_priv->fbdev);
        dev_priv->fbdev = NULL;
 }
+
+void intel_fbdev_set_suspend(struct drm_device *dev, int state)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       if (!dev_priv->fbdev)
+               return;
+
+       fb_set_suspend(dev_priv->fbdev->helper.fbdev, state);
+}
+
 MODULE_LICENSE("GPL and additional rights");
 
 void intel_fb_output_poll_changed(struct drm_device *dev)
index 8f510fd956b0f71fea65d9084b8bb38d54ccde99..fa860358add1560c2ada715a1d381f4860ef98b4 100644 (file)
@@ -654,10 +654,13 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
        if (nv_connector->edid && connector->display_info.bpc)
                return;
 
-       /* if not, we're out of options unless we're LVDS, default to 6bpc */
-       connector->display_info.bpc = 6;
-       if (nv_encoder->dcb->type != OUTPUT_LVDS)
+       /* if not, we're out of options unless we're LVDS, default to 8bpc */
+       if (nv_encoder->dcb->type != OUTPUT_LVDS) {
+               connector->display_info.bpc = 8;
                return;
+       }
+
+       connector->display_info.bpc = 6;
 
        /* LVDS: panel straps */
        if (bios->fp_no_ddc) {
index 8f4f914d9eab6bcbbc722973a2c0951ba84ca8c0..e2be95af2e52919c6a272009e23e01ea48c4165e 100644 (file)
@@ -315,8 +315,8 @@ nouveau_i2c_init(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvbios *bios = &dev_priv->vbios;
        struct nouveau_i2c_chan *port;
+       u8 version = 0x00, entries, recordlen;
        u8 *i2c, *entry, legacy[2][4] = {};
-       u8 version, entries, recordlen;
        int ret, i;
 
        INIT_LIST_HEAD(&dev_priv->i2c_ports);
@@ -346,12 +346,12 @@ nouveau_i2c_init(struct drm_device *dev)
                if (i2c[7]) legacy[1][1] = i2c[7];
        }
 
-       if (i2c && version >= 0x30) {
+       if (version >= 0x30) {
                entry     = i2c[1] + i2c;
                entries   = i2c[2];
                recordlen = i2c[3];
        } else
-       if (i2c) {
+       if (version) {
                entry     = i2c;
                entries   = 16;
                recordlen = 4;
index a3ae91fa81414779c541bda925528ead6de8b2fa..a4886b36d0faf771d6abc7d8aaa0983aca465850 100644 (file)
@@ -852,7 +852,7 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_pm;
 
-       if (!dev_priv->noaccel) {
+       if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
                ret = nouveau_card_channel_init(dev);
                if (ret)
                        goto out_fence;
index 083b3eada001fa6436cf1c63eb60132dabe8dda8..b5ff1f7b6f7ee4f3917d6d83e137ec02998a6d78 100644 (file)
@@ -588,8 +588,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if (encoder->crtc == crtc) {
                        radeon_encoder = to_radeon_encoder(encoder);
                        connector = radeon_get_connector_for_encoder(encoder);
-                       if (connector && connector->display_info.bpc)
-                               bpc = connector->display_info.bpc;
+                       /* if (connector && connector->display_info.bpc)
+                               bpc = connector->display_info.bpc; */
                        encoder_mode = atombios_get_encoder_mode(encoder);
                        is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
                        if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
@@ -965,7 +965,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                struct radeon_connector_atom_dig *dig_connector =
                        radeon_connector->con_priv;
                int dp_clock;
-               bpc = connector->display_info.bpc;
+
+               /* if (connector->display_info.bpc)
+                       bpc = connector->display_info.bpc; */
 
                switch (encoder_mode) {
                case ATOM_ENCODER_MODE_DP_MST:
index 6c62be226804ddf124e0d310d57bca6f314cb5e7..c57d85664e77991e6af217de06ea7c6493e9a6e6 100644 (file)
@@ -405,10 +405,13 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
 /* get bpc from the EDID */
 static int convert_bpc_to_bpp(int bpc)
 {
+#if 0
        if (bpc == 0)
                return 24;
        else
                return bpc * 3;
+#endif
+       return 24;
 }
 
 /* get the max pix clock supported by the link rate and lane num */
index 468b874336f9412b1e20b1018737f6eb7535436c..e607c4d7dd98bbccd9a709ab908b0c2c5b26a4b9 100644 (file)
@@ -541,7 +541,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
                dp_clock = dig_connector->dp_clock;
                dp_lane_count = dig_connector->dp_lane_count;
                hpd_id = radeon_connector->hpd.hpd;
-               bpc = connector->display_info.bpc;
+               /* bpc = connector->display_info.bpc; */
        }
 
        /* no dig encoder assigned */
@@ -1159,7 +1159,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
                dp_lane_count = dig_connector->dp_lane_count;
                connector_object_id =
                        (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-               bpc = connector->display_info.bpc;
+               /* bpc = connector->display_info.bpc; */
        }
 
        memset(&args, 0, sizeof(args));
index a58b37a2e65ac5d925f28e12c2bc1e5391669b47..70089d32b80feb7a4777f80b63c7b5c9c0c5901a 100644 (file)
@@ -80,6 +80,9 @@ struct evergreen_cs_track {
        bool                    cb_dirty;
        bool                    db_dirty;
        bool                    streamout_dirty;
+       u32                     htile_offset;
+       u32                     htile_surface;
+       struct radeon_bo        *htile_bo;
 };
 
 static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
@@ -144,6 +147,9 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track)
        track->db_s_read_bo = NULL;
        track->db_s_write_bo = NULL;
        track->db_dirty = true;
+       track->htile_bo = NULL;
+       track->htile_offset = 0xFFFFFFFF;
+       track->htile_surface = 0;
 
        for (i = 0; i < 4; i++) {
                track->vgt_strmout_size[i] = 0;
@@ -444,6 +450,62 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
        return 0;
 }
 
+static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
+                                               unsigned nbx, unsigned nby)
+{
+       struct evergreen_cs_track *track = p->track;
+       unsigned long size;
+
+       if (track->htile_bo == NULL) {
+               dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
+                               __func__, __LINE__, track->db_z_info);
+               return -EINVAL;
+       }
+
+       if (G_028ABC_LINEAR(track->htile_surface)) {
+               /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */
+               nbx = round_up(nbx, 16 * 8);
+               /* height is npipes htiles aligned == npipes * 8 pixel aligned */
+               nby = round_up(nby, track->npipes * 8);
+       } else {
+               switch (track->npipes) {
+               case 8:
+                       nbx = round_up(nbx, 64 * 8);
+                       nby = round_up(nby, 64 * 8);
+                       break;
+               case 4:
+                       nbx = round_up(nbx, 64 * 8);
+                       nby = round_up(nby, 32 * 8);
+                       break;
+               case 2:
+                       nbx = round_up(nbx, 32 * 8);
+                       nby = round_up(nby, 32 * 8);
+                       break;
+               case 1:
+                       nbx = round_up(nbx, 32 * 8);
+                       nby = round_up(nby, 16 * 8);
+                       break;
+               default:
+                       dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
+                                       __func__, __LINE__, track->npipes);
+                       return -EINVAL;
+               }
+       }
+       /* compute number of htile */
+       nbx = nbx / 8;
+       nby = nby / 8;
+       size = nbx * nby * 4;
+       size += track->htile_offset;
+
+       if (size > radeon_bo_size(track->htile_bo)) {
+               dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
+                               __func__, __LINE__, radeon_bo_size(track->htile_bo),
+                               size, nbx, nby);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
 {
        struct evergreen_cs_track *track = p->track;
@@ -530,6 +592,14 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
                return -EINVAL;
        }
 
+       /* hyperz */
+       if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
+               r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
+               if (r) {
+                       return r;
+               }
+       }
+
        return 0;
 }
 
@@ -617,6 +687,14 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
                return -EINVAL;
        }
 
+       /* hyperz */
+       if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
+               r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
+               if (r) {
+                       return r;
+               }
+       }
+
        return 0;
 }
 
@@ -850,7 +928,7 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)
                                return r;
                }
                /* Check depth buffer */
-               if (G_028800_Z_WRITE_ENABLE(track->db_depth_control)) {
+               if (G_028800_Z_ENABLE(track->db_depth_control)) {
                        r = evergreen_cs_track_validate_depth(p);
                        if (r)
                                return r;
@@ -1616,6 +1694,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->cb_color_bo[tmp] = reloc->robj;
                track->cb_dirty = true;
                break;
+       case DB_HTILE_DATA_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->htile_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->htile_bo = reloc->robj;
+               track->db_dirty = true;
+               break;
+       case DB_HTILE_SURFACE:
+               /* 8x8 only */
+               track->htile_surface = radeon_get_ib_value(p, idx);
+               track->db_dirty = true;
+               break;
        case CB_IMMED0_BASE:
        case CB_IMMED1_BASE:
        case CB_IMMED2_BASE:
@@ -1628,7 +1723,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_IMMED9_BASE:
        case CB_IMMED10_BASE:
        case CB_IMMED11_BASE:
-       case DB_HTILE_DATA_BASE:
        case SQ_PGM_START_FS:
        case SQ_PGM_START_ES:
        case SQ_PGM_START_VS:
index eb5708c7159dace94031b0b243859b09d4ce907a..b4eefc355f16d1c0628e5007038a2af4e0a4f5f1 100644 (file)
 #define   G_028008_SLICE_MAX(x)                        (((x) >> 13) & 0x7FF)
 #define   C_028008_SLICE_MAX                           0xFF001FFF
 #define DB_HTILE_DATA_BASE                             0x28014
+#define DB_HTILE_SURFACE                               0x28abc
+#define   S_028ABC_HTILE_WIDTH(x)                      (((x) & 0x1) << 0)
+#define   G_028ABC_HTILE_WIDTH(x)                      (((x) >> 0) & 0x1)
+#define   C_028ABC_HTILE_WIDTH                         0xFFFFFFFE
+#define   S_028ABC_HTILE_HEIGHT(x)                      (((x) & 0x1) << 1)
+#define   G_028ABC_HTILE_HEIGHT(x)                      (((x) >> 1) & 0x1)
+#define   C_028ABC_HTILE_HEIGHT                         0xFFFFFFFD
+#define   G_028ABC_LINEAR(x)                           (((x) >> 2) & 0x1)
 #define DB_Z_INFO                                      0x28040
 #       define Z_ARRAY_MODE(x)                          ((x) << 4)
 #       define DB_TILE_SPLIT(x)                         (((x) & 0x7) << 8)
index 0ec3f205f9c49ad25c6bb38f0c499d5ac8091ab6..b8e12af304a9657db9b5b906c2df1e289edb46f9 100644 (file)
@@ -78,6 +78,9 @@ struct r600_cs_track {
        bool                    cb_dirty;
        bool                    db_dirty;
        bool                    streamout_dirty;
+       struct radeon_bo        *htile_bo;
+       u64                     htile_offset;
+       u32                     htile_surface;
 };
 
 #define FMT_8_BIT(fmt, vc)   [fmt] = { 1, 1, 1, vc, CHIP_R600 }
@@ -321,6 +324,9 @@ static void r600_cs_track_init(struct r600_cs_track *track)
        track->db_depth_size_idx = 0;
        track->db_depth_control = 0xFFFFFFFF;
        track->db_dirty = true;
+       track->htile_bo = NULL;
+       track->htile_offset = 0xFFFFFFFF;
+       track->htile_surface = 0;
 
        for (i = 0; i < 4; i++) {
                track->vgt_strmout_size[i] = 0;
@@ -455,12 +461,256 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        return 0;
 }
 
+static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
+{
+       struct r600_cs_track *track = p->track;
+       u32 nviews, bpe, ntiles, size, slice_tile_max, tmp;
+       u32 height_align, pitch_align, depth_align;
+       u32 pitch = 8192;
+       u32 height = 8192;
+       u64 base_offset, base_align;
+       struct array_mode_checker array_check;
+       int array_mode;
+       volatile u32 *ib = p->ib->ptr;
+
+
+       if (track->db_bo == NULL) {
+               dev_warn(p->dev, "z/stencil with no depth buffer\n");
+               return -EINVAL;
+       }
+       switch (G_028010_FORMAT(track->db_depth_info)) {
+       case V_028010_DEPTH_16:
+               bpe = 2;
+               break;
+       case V_028010_DEPTH_X8_24:
+       case V_028010_DEPTH_8_24:
+       case V_028010_DEPTH_X8_24_FLOAT:
+       case V_028010_DEPTH_8_24_FLOAT:
+       case V_028010_DEPTH_32_FLOAT:
+               bpe = 4;
+               break;
+       case V_028010_DEPTH_X24_8_32_FLOAT:
+               bpe = 8;
+               break;
+       default:
+               dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
+               return -EINVAL;
+       }
+       if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
+               if (!track->db_depth_size_idx) {
+                       dev_warn(p->dev, "z/stencil buffer size not set\n");
+                       return -EINVAL;
+               }
+               tmp = radeon_bo_size(track->db_bo) - track->db_offset;
+               tmp = (tmp / bpe) >> 6;
+               if (!tmp) {
+                       dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
+                                       track->db_depth_size, bpe, track->db_offset,
+                                       radeon_bo_size(track->db_bo));
+                       return -EINVAL;
+               }
+               ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
+       } else {
+               size = radeon_bo_size(track->db_bo);
+               /* pitch in pixels */
+               pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
+               slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
+               slice_tile_max *= 64;
+               height = slice_tile_max / pitch;
+               if (height > 8192)
+                       height = 8192;
+               base_offset = track->db_bo_mc + track->db_offset;
+               array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
+               array_check.array_mode = array_mode;
+               array_check.group_size = track->group_size;
+               array_check.nbanks = track->nbanks;
+               array_check.npipes = track->npipes;
+               array_check.nsamples = track->nsamples;
+               array_check.blocksize = bpe;
+               if (r600_get_array_mode_alignment(&array_check,
+                                       &pitch_align, &height_align, &depth_align, &base_align)) {
+                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
+                                       G_028010_ARRAY_MODE(track->db_depth_info),
+                                       track->db_depth_info);
+                       return -EINVAL;
+               }
+               switch (array_mode) {
+               case V_028010_ARRAY_1D_TILED_THIN1:
+                       /* don't break userspace */
+                       height &= ~0x7;
+                       break;
+               case V_028010_ARRAY_2D_TILED_THIN1:
+                       break;
+               default:
+                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
+                                       G_028010_ARRAY_MODE(track->db_depth_info),
+                                       track->db_depth_info);
+                       return -EINVAL;
+               }
+
+               if (!IS_ALIGNED(pitch, pitch_align)) {
+                       dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
+                                       __func__, __LINE__, pitch, pitch_align, array_mode);
+                       return -EINVAL;
+               }
+               if (!IS_ALIGNED(height, height_align)) {
+                       dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
+                                       __func__, __LINE__, height, height_align, array_mode);
+                       return -EINVAL;
+               }
+               if (!IS_ALIGNED(base_offset, base_align)) {
+                       dev_warn(p->dev, "%s offset 0x%llx, 0x%llx, %d not aligned\n", __func__,
+                                       base_offset, base_align, array_mode);
+                       return -EINVAL;
+               }
+
+               ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
+               nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
+               tmp = ntiles * bpe * 64 * nviews;
+               if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
+                       dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
+                                       array_mode,
+                                       track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
+                                       radeon_bo_size(track->db_bo));
+                       return -EINVAL;
+               }
+       }
+
+       /* hyperz */
+       if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
+               unsigned long size;
+               unsigned nbx, nby;
+
+               if (track->htile_bo == NULL) {
+                       dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
+                                __func__, __LINE__, track->db_depth_info);
+                       return -EINVAL;
+               }
+               if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
+                       dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n",
+                                __func__, __LINE__, track->db_depth_size);
+                       return -EINVAL;
+               }
+
+               nbx = pitch;
+               nby = height;
+               if (G_028D24_LINEAR(track->htile_surface)) {
+                       /* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */
+                       nbx = round_up(nbx, 16 * 8);
+                       /* nby is npipes htiles aligned == npipes * 8 pixel aligned */
+                       nby = round_up(nby, track->npipes * 8);
+               } else {
+                       /* htile widht & nby (8 or 4) make 2 bits number */
+                       tmp = track->htile_surface & 3;
+                       /* align is htile align * 8, htile align vary according to
+                        * number of pipe and tile width and nby
+                        */
+                       switch (track->npipes) {
+                       case 8:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 64 * 8);
+                                       nby = round_up(nby, 64 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 64 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 4:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 64 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 2:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 16 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 1:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 16 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 16 * 8);
+                                       nby = round_up(nby, 8 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       default:
+                               dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
+                                        __func__, __LINE__, track->npipes);
+                               return -EINVAL;
+                       }
+               }
+               /* compute number of htile */
+               nbx = G_028D24_HTILE_WIDTH(track->htile_surface) ? nbx / 8 : nbx / 4;
+               nby = G_028D24_HTILE_HEIGHT(track->htile_surface) ? nby / 8 : nby / 4;
+               size = nbx * nby * 4;
+               size += track->htile_offset;
+
+               if (size > radeon_bo_size(track->htile_bo)) {
+                       dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
+                                __func__, __LINE__, radeon_bo_size(track->htile_bo),
+                                size, nbx, nby);
+                       return -EINVAL;
+               }
+       }
+
+       track->db_dirty = false;
+       return 0;
+}
+
 static int r600_cs_track_check(struct radeon_cs_parser *p)
 {
        struct r600_cs_track *track = p->track;
        u32 tmp;
        int r, i;
-       volatile u32 *ib = p->ib->ptr;
 
        /* on legacy kernel we don't perform advanced check */
        if (p->rdev == NULL)
@@ -513,124 +763,14 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
                track->cb_dirty = false;
        }
 
-       if (track->db_dirty) {
-               /* Check depth buffer */
-               if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
-                       G_028800_Z_ENABLE(track->db_depth_control)) {
-                       u32 nviews, bpe, ntiles, size, slice_tile_max;
-                       u32 height, height_align, pitch, pitch_align, depth_align;
-                       u64 base_offset, base_align;
-                       struct array_mode_checker array_check;
-                       int array_mode;
-
-                       if (track->db_bo == NULL) {
-                               dev_warn(p->dev, "z/stencil with no depth buffer\n");
-                               return -EINVAL;
-                       }
-                       if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
-                               dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
-                               return -EINVAL;
-                       }
-                       switch (G_028010_FORMAT(track->db_depth_info)) {
-                       case V_028010_DEPTH_16:
-                               bpe = 2;
-                               break;
-                       case V_028010_DEPTH_X8_24:
-                       case V_028010_DEPTH_8_24:
-                       case V_028010_DEPTH_X8_24_FLOAT:
-                       case V_028010_DEPTH_8_24_FLOAT:
-                       case V_028010_DEPTH_32_FLOAT:
-                               bpe = 4;
-                               break;
-                       case V_028010_DEPTH_X24_8_32_FLOAT:
-                               bpe = 8;
-                               break;
-                       default:
-                               dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
-                               return -EINVAL;
-                       }
-                       if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
-                               if (!track->db_depth_size_idx) {
-                                       dev_warn(p->dev, "z/stencil buffer size not set\n");
-                                       return -EINVAL;
-                               }
-                               tmp = radeon_bo_size(track->db_bo) - track->db_offset;
-                               tmp = (tmp / bpe) >> 6;
-                               if (!tmp) {
-                                       dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
-                                                       track->db_depth_size, bpe, track->db_offset,
-                                                       radeon_bo_size(track->db_bo));
-                                       return -EINVAL;
-                               }
-                               ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
-                       } else {
-                               size = radeon_bo_size(track->db_bo);
-                               /* pitch in pixels */
-                               pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
-                               slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
-                               slice_tile_max *= 64;
-                               height = slice_tile_max / pitch;
-                               if (height > 8192)
-                                       height = 8192;
-                               base_offset = track->db_bo_mc + track->db_offset;
-                               array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
-                               array_check.array_mode = array_mode;
-                               array_check.group_size = track->group_size;
-                               array_check.nbanks = track->nbanks;
-                               array_check.npipes = track->npipes;
-                               array_check.nsamples = track->nsamples;
-                               array_check.blocksize = bpe;
-                               if (r600_get_array_mode_alignment(&array_check,
-                                                                 &pitch_align, &height_align, &depth_align, &base_align)) {
-                                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
-                                                G_028010_ARRAY_MODE(track->db_depth_info),
-                                                track->db_depth_info);
-                                       return -EINVAL;
-                               }
-                               switch (array_mode) {
-                               case V_028010_ARRAY_1D_TILED_THIN1:
-                                       /* don't break userspace */
-                                       height &= ~0x7;
-                                       break;
-                               case V_028010_ARRAY_2D_TILED_THIN1:
-                                       break;
-                               default:
-                                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
-                                                G_028010_ARRAY_MODE(track->db_depth_info),
-                                                track->db_depth_info);
-                                       return -EINVAL;
-                               }
-
-                               if (!IS_ALIGNED(pitch, pitch_align)) {
-                                       dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
-                                                __func__, __LINE__, pitch, pitch_align, array_mode);
-                                       return -EINVAL;
-                               }
-                               if (!IS_ALIGNED(height, height_align)) {
-                                       dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
-                                                __func__, __LINE__, height, height_align, array_mode);
-                                       return -EINVAL;
-                               }
-                               if (!IS_ALIGNED(base_offset, base_align)) {
-                                       dev_warn(p->dev, "%s offset[%d] 0x%llx, 0x%llx, %d not aligned\n", __func__, i,
-                                                base_offset, base_align, array_mode);
-                                       return -EINVAL;
-                               }
-
-                               ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
-                               nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
-                               tmp = ntiles * bpe * 64 * nviews;
-                               if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
-                                       dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
-                                                array_mode,
-                                                track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
-                                                radeon_bo_size(track->db_bo));
-                                       return -EINVAL;
-                               }
-                       }
-               }
-               track->db_dirty = false;
+       /* Check depth buffer */
+       if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
+               G_028800_Z_ENABLE(track->db_depth_control))) {
+               r = r600_cs_track_validate_db(p);
+               if (r)
+                       return r;
        }
+
        return 0;
 }
 
@@ -1244,6 +1384,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
+               r = r600_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->htile_offset = radeon_get_ib_value(p, idx) << 8;
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->htile_bo = reloc->robj;
+               track->db_dirty = true;
+               break;
+       case DB_HTILE_SURFACE:
+               track->htile_surface = radeon_get_ib_value(p, idx);
+               track->db_dirty = true;
+               break;
        case SQ_PGM_START_FS:
        case SQ_PGM_START_ES:
        case SQ_PGM_START_VS:
index 3568a2e345faf6d4c4682aadae04a6c192f8b7da..59f9c993cc31b4cdb550b85b5b99de588b5430b0 100644 (file)
 #define                PREZ_MUST_WAIT_FOR_POSTZ_DONE                   (1 << 31)
 #define        DB_DEPTH_BASE                                   0x2800C
 #define        DB_HTILE_DATA_BASE                              0x28014
+#define        DB_HTILE_SURFACE                                0x28D24
+#define   S_028D24_HTILE_WIDTH(x)                      (((x) & 0x1) << 0)
+#define   G_028D24_HTILE_WIDTH(x)                      (((x) >> 0) & 0x1)
+#define   C_028D24_HTILE_WIDTH                         0xFFFFFFFE
+#define   S_028D24_HTILE_HEIGHT(x)                      (((x) & 0x1) << 1)
+#define   G_028D24_HTILE_HEIGHT(x)                      (((x) >> 1) & 0x1)
+#define   C_028D24_HTILE_HEIGHT                         0xFFFFFFFD
+#define   G_028D24_LINEAR(x)                           (((x) >> 2) & 0x1)
 #define        DB_WATERMARKS                                   0x9838
 #define                DEPTH_FREE(x)                                   ((x) << 0)
 #define                DEPTH_FLUSH(x)                                  ((x) << 5)
index 91541e63d582706416b8bba9365c4930c6dadf29..6f70158d34e41f979ade9268cadeab8905ea4e81 100644 (file)
@@ -233,7 +233,17 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
                bo->pin_count++;
                if (gpu_addr)
                        *gpu_addr = radeon_bo_gpu_offset(bo);
-               WARN_ON_ONCE(max_offset != 0);
+
+               if (max_offset != 0) {
+                       u64 domain_start;
+
+                       if (domain == RADEON_GEM_DOMAIN_VRAM)
+                               domain_start = bo->rdev->mc.vram_start;
+                       else
+                               domain_start = bo->rdev->mc.gtt_start;
+                       WARN_ON_ONCE((*gpu_addr - domain_start) > max_offset);
+               }
+
                return 0;
        }
        radeon_ttm_placement_from_domain(bo, domain);
index aea63c4158527436f9292ce32006d04fa4801629..0f656b111c15f913f6c09045f045b81bf016c2b2 100644 (file)
@@ -509,7 +509,6 @@ cayman 0x9400
 0x00028AA8 IA_MULTI_VGT_PARAM
 0x00028AB4 VGT_REUSE_OFF
 0x00028AB8 VGT_VTX_CNT_EN
-0x00028ABC DB_HTILE_SURFACE
 0x00028AC0 DB_SRESULTS_COMPARE_STATE0
 0x00028AC4 DB_SRESULTS_COMPARE_STATE1
 0x00028AC8 DB_PRELOAD_CONTROL
index 77c37202376f459b03271e36a2ebfed24353a9c9..b912a37689bf818a0fccd576f6436f71e4e936ff 100644 (file)
@@ -519,7 +519,6 @@ evergreen 0x9400
 0x00028AA4 VGT_INSTANCE_STEP_RATE_1
 0x00028AB4 VGT_REUSE_OFF
 0x00028AB8 VGT_VTX_CNT_EN
-0x00028ABC DB_HTILE_SURFACE
 0x00028AC0 DB_SRESULTS_COMPARE_STATE0
 0x00028AC4 DB_SRESULTS_COMPARE_STATE1
 0x00028AC8 DB_PRELOAD_CONTROL
index 626c24ea0b563b56c863fe24d591cd9ef9d0671d..5e659b034d9a379d362327541480b2eeef70bf61 100644 (file)
@@ -713,7 +713,6 @@ r600 0x9400
 0x0000A710 TD_VS_SAMPLER17_BORDER_RED
 0x00009508 TA_CNTL_AUX
 0x0002802C DB_DEPTH_CLEAR
-0x00028D24 DB_HTILE_SURFACE
 0x00028D34 DB_PREFETCH_LIMIT
 0x00028D30 DB_PRELOAD_CONTROL
 0x00028D0C DB_RENDER_CONTROL
index 8305d29459bd1e766cca550e860b358f5b4382c2..519ce8b9c1427af878d495cb89addf42b20db1ef 100644 (file)
@@ -53,8 +53,8 @@
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 /* Insmod parameters */
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 6c6b240a782eebdbe3d3908435a17c3bc50ba513..ce86c5e3c2c2ae6211694b92ff50e19573cb35ec 100644 (file)
@@ -59,7 +59,7 @@ static int mc13783_adc_read(struct device *dev,
 
        ret = mc13xxx_adc_do_conversion(priv->mc13xxx,
                        MC13XXX_ADC_MODE_MULT_CHAN,
-                       channel, sample);
+                       channel, 0, 0, sample);
        if (ret)
                return ret;
 
index 834e49d1827b134763d04d8fa6fa58736f8621e0..d6b0bdd48651ecfa660be2ed8589252c2a6b03d7 100644 (file)
@@ -71,8 +71,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in minutes. 2<= timeout <=255 (default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index acba1c686c65d6c560fdf47c126b189376c7856c..7f0b83219744e52aa7cd68a7ac5ea6edc49537d1 100644 (file)
@@ -15,7 +15,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
  * ------------------------------------------------------------------------- */
 
 /* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki
@@ -111,7 +112,7 @@ static int sclhi(struct i2c_algo_bit_data *adap)
                                break;
                        return -ETIMEDOUT;
                }
-               cond_resched();
+               cpu_relax();
        }
 #ifdef DEBUG
        if (jiffies != start && i2c_debug >= 3)
index beb9ffe2564bc77ffb474ef1346a49c2600c89a5..73133b1063f012416d2a957f3fc2432ace395439 100644 (file)
@@ -15,7 +15,8 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index 5eebf562ff31b9094fffa7c0300003223382affe..5c2379522aa9fb8d9e8c0e1a6635e4429443289f 100644 (file)
@@ -16,7 +16,8 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301 USA.
  *
  * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
  * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey
index 5263a9eeb8d7e4df7cf5a2f801c7c0da57f5c043..1ec703ee788d2cc2c3467917d989f6c1c3c16973 100644 (file)
@@ -16,7 +16,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                 */
 /* --------------------------------------------------------------------        */
 
 /* With some changes from Frodo Looijaard <frodol@dds.nl> */
index 71c1b0a7535ccad12a2d95068890359ce74b7e3e..d2c5095deeaca5dc0324b3786ff056ec09447275 100644 (file)
@@ -103,6 +103,7 @@ config I2C_I801
            Patsburg (PCH)
            DH89xxCC (PCH)
            Panther Point (PCH)
+           Lynx Point (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
index 86796488ef4fd9215809a883a436c0e0fa0bcf4f..ed9f48d566dba7d4dab71d1217ce792c7dc3005a 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <mach/hardware.h>
 #include <asm/hardware/ioc.h>
-#include <asm/system.h>
 
 #define FORCE_ONES     0xdc
 #define SCL            0x02
index 5d2e2816831f21dcd73912e8d33a9407f6df0b62..ae2945a5e00713bfda7b268ac48fbb42f4ba5214 100644 (file)
@@ -2,7 +2,7 @@
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
     <mdsxyz123@yahoo.com>
-    Copyright (C) 2007, 2008   Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2007 - 2012  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2010         Intel Corporation,
                                David Woodhouse <dwmw2@infradead.org>
 
@@ -51,6 +51,7 @@
   Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
   DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
   Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
+  Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
 #define SMBHSTCNT_KILL         2
 
 /* Other settings */
-#define MAX_TIMEOUT            100
+#define MAX_RETRIES            400
 #define ENABLE_INT9            0       /* set to 0x01 to enable - untested */
 
 /* I801 command constants */
 #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS    0x8c22
 
 struct i801_priv {
        struct i2c_adapter adapter;
@@ -215,7 +217,7 @@ static int i801_check_post(struct i801_priv *priv, int status, int timeout)
                dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
                outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
                       SMBHSTCNT(priv));
-               msleep(1);
+               usleep_range(1000, 2000);
                outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
                       SMBHSTCNT(priv));
 
@@ -272,11 +274,11 @@ static int i801_transaction(struct i801_priv *priv, int xact)
 
        /* We will always wait for a fraction of a second! */
        do {
-               msleep(1);
+               usleep_range(250, 500);
                status = inb_p(SMBHSTSTS(priv));
-       } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
+       } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES));
 
-       result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
+       result = i801_check_post(priv, status, timeout > MAX_RETRIES);
        if (result < 0)
                return result;
 
@@ -291,12 +293,12 @@ static void i801_wait_hwpec(struct i801_priv *priv)
        int status;
 
        do {
-               msleep(1);
+               usleep_range(250, 500);
                status = inb_p(SMBHSTSTS(priv));
        } while ((!(status & SMBHSTSTS_INTR))
-                && (timeout++ < MAX_TIMEOUT));
+                && (timeout++ < MAX_RETRIES));
 
-       if (timeout > MAX_TIMEOUT)
+       if (timeout > MAX_RETRIES)
                dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n");
 
        outb_p(status, SMBHSTSTS(priv));
@@ -380,12 +382,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
                /* We will always wait for a fraction of a second! */
                timeout = 0;
                do {
-                       msleep(1);
+                       usleep_range(250, 500);
                        status = inb_p(SMBHSTSTS(priv));
                } while ((!(status & SMBHSTSTS_BYTE_DONE))
-                        && (timeout++ < MAX_TIMEOUT));
+                        && (timeout++ < MAX_RETRIES));
 
-               result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
+               result = i801_check_post(priv, status, timeout > MAX_RETRIES);
                if (result < 0)
                        return result;
 
@@ -633,6 +635,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
        { 0, }
 };
 
index 6561d275b8cf20fd9ed056c1963d66fd4c318899..f90a6057508dd7ffe0dabd6f30694ab9b06a36f4 100644 (file)
@@ -47,7 +47,7 @@
 #define SMBBLKDAT      (0x20 + sch_smba)
 
 /* Other settings */
-#define MAX_TIMEOUT    500
+#define MAX_RETRIES    5000
 
 /* I2C constants */
 #define SCH_QUICK              0x00
@@ -68,7 +68,7 @@ static int sch_transaction(void)
 {
        int temp;
        int result = 0;
-       int timeout = 0;
+       int retries = 0;
 
        dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
                "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
@@ -100,12 +100,12 @@ static int sch_transaction(void)
        outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
 
        do {
-               msleep(1);
+               usleep_range(100, 200);
                temp = inb(SMBHSTSTS) & 0x0f;
-       } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
+       } while ((temp & 0x08) && (retries++ < MAX_RETRIES));
 
        /* If the SMBus is still busy, we give up */
-       if (timeout > MAX_TIMEOUT) {
+       if (retries > MAX_RETRIES) {
                dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
                result = -ETIMEDOUT;
        }
index 10274ffb66d73693ebbe097026156792ddeb8ea6..f24cc64e2e8c6a1288f0cdc0f38c545723057477 100644 (file)
@@ -13,7 +13,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index e9c18939eda70e78951dd41deaa73046ae4fdd5b..feb7dc359186495ead9dbff484e0ab76507eff0c 100644 (file)
@@ -14,7 +14,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
index 9f9c57ff6708506d5e5c916c956c2ce7bcf91ed0..18a8fd21d2c226741445fdc5bf12ed306e10ff7e 100644 (file)
@@ -13,7 +13,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #include <linux/rwsem.h>
index 10e7f1e7658610b8e2b697cf6e355a999aa4f5b6..45048323b75eab01d5875cb05464207c2eb614b3 100644 (file)
@@ -17,7 +17,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
 */
 
 /* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.
index f61ccc1e5ea3ea7a350af1cc3ec7858bf0f5dbe8..9836d08f7a77a6450ce40e0e242de32ca2ba705c 100644 (file)
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index ed699c5aa79d033496f0a6eb1b1eb75b6de0e4c6..e0df9b6c66b34132dac3249fc58ad6ee01b758ca 100644 (file)
@@ -393,18 +393,7 @@ static struct i2c_driver pca9541_driver = {
        .id_table = pca9541_id,
 };
 
-static int __init pca9541_init(void)
-{
-       return i2c_add_driver(&pca9541_driver);
-}
-
-static void __exit pca9541_exit(void)
-{
-       i2c_del_driver(&pca9541_driver);
-}
-
-module_init(pca9541_init);
-module_exit(pca9541_exit);
+module_i2c_driver(pca9541_driver);
 
 MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
 MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
index 6f89536646365db2cf316d166c2df23959d2988e..0e37ef27aa129e614bf99b5e9d8f4f2dc5f72527 100644 (file)
@@ -284,18 +284,7 @@ static struct i2c_driver pca954x_driver = {
        .id_table       = pca954x_id,
 };
 
-static int __init pca954x_init(void)
-{
-       return i2c_add_driver(&pca954x_driver);
-}
-
-static void __exit pca954x_exit(void)
-{
-       i2c_del_driver(&pca954x_driver);
-}
-
-module_init(pca954x_init);
-module_exit(pca954x_exit);
+module_i2c_driver(pca954x_driver);
 
 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 MODULE_DESCRIPTION("PCA954x I2C mux/switch driver");
index d2f3db3cf3ed523db978fa7e4f4d1adea9ef7c27..28e344ea514cc18ba8060c6cb6d6d2beb0a2a70b 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
index 8bbfe5557c7bbd178cea496ef8abe65ee9f5041e..e03f4f19c1d61af084012a8714b5067f4d1a6c41 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/blkdev.h>
 #include <linux/ide.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #define DRV_NAME "qd65xx"
index 9a3fbfca9b415107d10c231043a92d59af665762..fd05f48f6b0b649305014e22967e41bf4dcafefb 100644 (file)
@@ -42,7 +42,6 @@
  */
 
 
-#include <asm/system.h>
 #include "ehca_classes.h"
 #include "ehca_tools.h"
 #include "ehca_qes.h"
index e46a86776a6bd247d47bd92dbbaa2e0c8657c9b7..64ca7113ff28cb25ee301ddb5adf3c049cec9c9c 100644 (file)
@@ -17,7 +17,7 @@
 int input_event_from_user(const char __user *buffer,
                          struct input_event *event)
 {
-       if (INPUT_COMPAT_TEST) {
+       if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) {
                struct input_event_compat compat_event;
 
                if (copy_from_user(&compat_event, buffer,
@@ -41,7 +41,7 @@ int input_event_from_user(const char __user *buffer,
 int input_event_to_user(char __user *buffer,
                        const struct input_event *event)
 {
-       if (INPUT_COMPAT_TEST) {
+       if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) {
                struct input_event_compat compat_event;
 
                compat_event.time.tv_sec = event->time.tv_sec;
index 22be27b424def00dbd8cc0167439b508b2564b78..148f66fe3205c7a3059a26a5f9e4748dd4c4bb50 100644 (file)
@@ -67,7 +67,7 @@ struct ff_effect_compat {
 
 static inline size_t input_event_size(void)
 {
-       return INPUT_COMPAT_TEST ?
+       return (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) ?
                sizeof(struct input_event_compat) : sizeof(struct input_event);
 }
 
index c24ec2d5f9266cb969bd3a73ea229c08adcc8d9b..26043cc6a0165f80a36e7ee31436cc128a318de1 100644 (file)
@@ -13,7 +13,6 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/joystick.h>
index 0bc86204213e187106c54c560774884ac632f09d..24044dacbf70086a90c6191dc9e310a0608b84ca 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 
-#include <asm/system.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 
index f2e0cbc5ab646c76267731f1a1280041ba50c1ca..f9ce1835e4d71c7a2cf3f53231fd1703e3386b7a 100644 (file)
@@ -105,6 +105,8 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, info);
+       device_init_wakeup(&pdev->dev, 1);
+
        return 0;
 
 out_irq:
@@ -129,10 +131,34 @@ static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_onkey_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag |= 1 << PM8607_IRQ_ONKEY;
+       return 0;
+}
+static int pm860x_onkey_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag &= ~(1 << PM8607_IRQ_ONKEY);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_onkey_pm_ops, pm860x_onkey_suspend, pm860x_onkey_resume);
+
 static struct platform_driver pm860x_onkey_driver = {
        .driver         = {
                .name   = "88pm860x-onkey",
                .owner  = THIS_MODULE,
+               .pm     = &pm860x_onkey_pm_ops,
        },
        .probe          = pm860x_onkey_probe,
        .remove         = __devexit_p(pm860x_onkey_remove),
index ff5f61a0fd3ad1eb071e600e5e37fb15fb4ca61a..5fa99341a39d1b58d725cc663512dead25925b80 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 5c4a692bf73aee120aaf928fb2d33104f51dea65..d1c43236b12596cc0b7c732485cd7f7271484030 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/atarihw.h>
 #include <asm/atarikb.h>
index be3316073ae7db4f8a21c80f0207893ea3dd433d..09a089996ded673788e8302b7854e2a4669960d8 100644 (file)
@@ -71,7 +71,6 @@
 #include <linux/slab.h>
 #include <linux/hil.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* Machine-specific abstraction */
 
index 558200e96d0f22a1d586f578f5df62944646b21d..61da763b120983bf0ab9c112f3a9f797ef5f56e5 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/ip32/mace.h>
 #include <asm/ip32/ip32_ints.h>
 
index 58b224498b35ad7d3fc6c2b034780f67921f7f9f..2af5df6a8fba76855f5a354fafaeb958459feecc 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <mach/hardware.h>
 #include <asm/hardware/iomd.h>
-#include <asm/system.h>
 
 MODULE_AUTHOR("Vojtech Pavlik, Russell King");
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
index 5ebabe3fc84521e2ad18149f3f3092a8be686231..3897667075340efda6b382dc16b4e2d9e0f5181d 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/hardware/sa1111.h>
 
index ede02743eac1997b426a7970f96429a486ea4059..48dc5b0d26f1a0b59039532318967ec5c500b862 100644 (file)
@@ -39,6 +39,7 @@ struct mc13783_ts_priv {
        struct delayed_work work;
        struct workqueue_struct *workq;
        unsigned int sample[4];
+       struct mc13xxx_ts_platform_data *touch;
 };
 
 static irqreturn_t mc13783_ts_handler(int irq, void *data)
@@ -125,7 +126,9 @@ static void mc13783_ts_work(struct work_struct *work)
        unsigned int channel = 12;
 
        if (mc13xxx_adc_do_conversion(priv->mc13xxx,
-                               mode, channel, priv->sample) == 0)
+                               mode, channel,
+                               priv->touch->ato, priv->touch->atox,
+                               priv->sample) == 0)
                mc13783_ts_report_sample(priv);
 }
 
@@ -179,6 +182,12 @@ static int __init mc13783_ts_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
        priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
        priv->idev = idev;
+       priv->touch = dev_get_platdata(&pdev->dev);
+       if (!priv->touch) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               ret = -ENODEV;
+               goto err_free_mem;
+       }
 
        /*
         * We need separate workqueue because mc13783_adc_do_conversion
index 44b50cc645e67eac4c3da8491c9a4e833c26e3e9..c21353d8e91562f9318f948aa2dc4cf49ab33546 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/serial.h>
 #include <linux/major.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
index 33e3c94887d86a0bc15c58aefb5d52dcc2dbda70..c644557ae614d2e56d4fb35cb2c9dc55d6e8c9c8 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
index fe254e74a850de001ea8226431755dd560bbb540..a8c4d3fc9a6d6d8d7000ae8f6a5a6d4b02ca3d34 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index 68f50495d166b25deedab36a5ff7b477b631622f..f0dfc0c976eb780cfd131478c964c00ad9e4c71f 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index bfe94284b0d59b9c41b1a1a87d83d1269aff4bd8..4deac451807cb5891d12bdd9f2bd1efddffc113a 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index 7f3c54d404748107d434bfd253d00166f8728650..c59e8d2c067506b3dd7e39b45f36a2618f5574f2 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/signal.h>      /* used in new tty drivers */
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/types.h>
 
index 682911f8113821368c3599b77e27a7e8475211c2..a18e639b40d7e4c354812092c494e46f98618235 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <linux/isdnif.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 
index 4ca00624bd1860ed3b1f29e27ea79b59b47dc46d..5b61aaf7ac0f3faa565430fd1acafef8162afd20 100644 (file)
@@ -114,6 +114,27 @@ static inline int __blink_ctl_mask(int port)
        return ret;
 }
 
+static int led_power_set(struct pm860x_chip *chip, int port, int on)
+{
+       int ret = -EINVAL;
+
+       switch (port) {
+       case PM8606_LED1_RED:
+       case PM8606_LED1_GREEN:
+       case PM8606_LED1_BLUE:
+               ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) :
+                       pm8606_osc_disable(chip, RGB1_ENABLE);
+               break;
+       case PM8606_LED2_RED:
+       case PM8606_LED2_GREEN:
+       case PM8606_LED2_BLUE:
+               ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) :
+                       pm8606_osc_disable(chip, RGB2_ENABLE);
+               break;
+       }
+       return ret;
+}
+
 static void pm860x_led_work(struct work_struct *work)
 {
 
@@ -126,6 +147,7 @@ static void pm860x_led_work(struct work_struct *work)
        chip = led->chip;
        mutex_lock(&led->lock);
        if ((led->current_brightness == 0) && led->brightness) {
+               led_power_set(chip, led->port, 1);
                if (led->iset) {
                        pm860x_set_bits(led->i2c, __led_off(led->port),
                                        LED_CURRENT_MASK, led->iset);
@@ -149,6 +171,7 @@ static void pm860x_led_work(struct work_struct *work)
                                        LED_CURRENT_MASK, 0);
                        mask = __blink_ctl_mask(led->port);
                        pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+                       led_power_set(chip, led->port, 0);
                }
        }
        led->current_brightness = led->brightness;
index b6ef8f590764926a238051115ae655af7a61942e..87de8d9bcfada8f3ca56d1952dda4342fc0dcc32 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/pgtable.h>
 #include <asm/hydra.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 
index c60d025044ee5ba2009b43717fb2273cf3c80c19..fc71723cbc485a11d4eb97c7911955a5a6aa7a72 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 
 #undef DEBUG
index 0ff92c2080055c50e9a90518888be3155c1a0ad4..97cfc5ac9fd042aa074d80836b50a21dab5301cd 100644 (file)
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/macio.h>
 
index 46c4e95f10d6a904445e643942e632dfc69f016f..3b4a157714b128e1f03f2cb12e8c57bd9932a8e7 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/macio.h>
 
index 971bc9582a5fa488c283a686123f14de88fb51b2..86511c570dd8c16cade3c153c3f1a1d497fdc573 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/mac_via.h>
 #endif
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/init.h>
 
 static volatile unsigned char __iomem *via;
index c9570fcf1cce10fdf06a607aba75d31331011668..3725f088f17e22f65b6eebf4403c49a086004716 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
-#include <asm/system.h>
 
 static volatile unsigned char *via;
 
index 6cccd60c594e3ae3ee73a6cf6ee98ce9543eead4..22b8ce4191ccd69d6b8740c61a71791efafd31bf 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/pmac_feature.h>
index aeb30d07d5a29bd9981759d3cc91ab535520ea9c..a00ee41f0573ad458fca83b00be773d0f70716fe 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/mac_via.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
index 647c6add2193e63d9bcec2be088ac2f28096a962..4d6a90a1372bf7d3c01f484dac8c24501ddd6edf 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/pmac_low_i2c.h>
 
index 30e6195e19d4ddca5c25f6d26534e7a5e6c55785..04067e073aa956ee89e14b1898dbd5c0154c6c2c 100644 (file)
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 749d174b0dc6f58998b2b21fd88cd39001405725..fc13d0f2663bb2475ca4a97a9e43d84302a48162 100644 (file)
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 344273235124e94aef27fec53d68f7b963b0059d..a9430ed4f36ce1c418f5e16ab7af4519bf60281c 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 43137b421f92048cde69327399d3e4c0024a692a..3c2be5193fd585b12810916d0feffce7754b2fef 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 3c193504bb8002d9aa8d497976c119967a63700c..1cc4e4953d891b2becb766dff4db56397f311b53 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index faa4741df6d3f7fca87e79b8a5f788b5d1b87218..10f122a3a8566acc5a1046b4a9b35ef04ad45fab 100644 (file)
@@ -277,8 +277,8 @@ config DM_MIRROR
          needed for live data migration tools such as 'pvmove'.
 
 config DM_RAID
-       tristate "RAID 1/4/5/6 target (EXPERIMENTAL)"
-       depends on BLK_DEV_DM && EXPERIMENTAL
+       tristate "RAID 1/4/5/6 target"
+       depends on BLK_DEV_DM
        select MD_RAID1
        select MD_RAID456
        select BLK_DEV_MD
@@ -359,8 +359,8 @@ config DM_DELAY
        If unsure, say N.
 
 config DM_UEVENT
-       bool "DM uevents (EXPERIMENTAL)"
-       depends on BLK_DEV_DM && EXPERIMENTAL
+       bool "DM uevents"
+       depends on BLK_DEV_DM
        ---help---
        Generate udev events for DM events.
 
@@ -370,4 +370,24 @@ config DM_FLAKEY
        ---help---
          A target that intermittently fails I/O for debugging purposes.
 
+config DM_VERITY
+       tristate "Verity target support (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select CRYPTO
+       select CRYPTO_HASH
+       select DM_BUFIO
+       ---help---
+         This device-mapper target creates a read-only device that
+         transparently validates the data on one underlying device against
+         a pre-generated tree of cryptographic checksums stored on a second
+         device.
+
+         You'll need to activate the digests you're going to use in the
+         cryptoapi configuration.
+
+         To compile this code as a module, choose M here: the module will
+         be called dm-verity.
+
+         If unsure, say N.
+
 endif # MD
index 046860c7a1666e54f5cdd33a40901fb2b84dd090..8b2e0dffe82e9c7fd4ca571381ea2fdfb0d77986 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_DM_LOG_USERSPACE)        += dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)          += dm-zero.o
 obj-$(CONFIG_DM_RAID)  += dm-raid.o
 obj-$(CONFIG_DM_THIN_PROVISIONING)     += dm-thin-pool.o
+obj-$(CONFIG_DM_VERITY)                += dm-verity.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs                    += dm-uevent.o
index b6e58c7b6df544fa3a9f2f2cff94a7da6af72c3f..cc06a1e5242395c9d05e26b76c71849490f348af 100644 (file)
@@ -578,7 +578,7 @@ static void write_endio(struct bio *bio, int error)
        struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
 
        b->write_error = error;
-       if (error) {
+       if (unlikely(error)) {
                struct dm_bufio_client *c = b->c;
                (void)cmpxchg(&c->async_write_error, 0, error);
        }
@@ -697,13 +697,20 @@ static void __wait_for_free_buffer(struct dm_bufio_client *c)
        dm_bufio_lock(c);
 }
 
+enum new_flag {
+       NF_FRESH = 0,
+       NF_READ = 1,
+       NF_GET = 2,
+       NF_PREFETCH = 3
+};
+
 /*
  * Allocate a new buffer. If the allocation is not possible, wait until
  * some other thread frees a buffer.
  *
  * May drop the lock and regain it.
  */
-static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c)
+static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c, enum new_flag nf)
 {
        struct dm_buffer *b;
 
@@ -726,6 +733,9 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client
                                return b;
                }
 
+               if (nf == NF_PREFETCH)
+                       return NULL;
+
                if (!list_empty(&c->reserved_buffers)) {
                        b = list_entry(c->reserved_buffers.next,
                                       struct dm_buffer, lru_list);
@@ -743,9 +753,12 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client
        }
 }
 
-static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c)
+static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c, enum new_flag nf)
 {
-       struct dm_buffer *b = __alloc_buffer_wait_no_callback(c);
+       struct dm_buffer *b = __alloc_buffer_wait_no_callback(c, nf);
+
+       if (!b)
+               return NULL;
 
        if (c->alloc_callback)
                c->alloc_callback(b);
@@ -865,32 +878,23 @@ static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
  * Getting a buffer
  *--------------------------------------------------------------*/
 
-enum new_flag {
-       NF_FRESH = 0,
-       NF_READ = 1,
-       NF_GET = 2
-};
-
 static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
-                                    enum new_flag nf, struct dm_buffer **bp,
-                                    int *need_submit)
+                                    enum new_flag nf, int *need_submit)
 {
        struct dm_buffer *b, *new_b = NULL;
 
        *need_submit = 0;
 
        b = __find(c, block);
-       if (b) {
-               b->hold_count++;
-               __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
-                            test_bit(B_WRITING, &b->state));
-               return b;
-       }
+       if (b)
+               goto found_buffer;
 
        if (nf == NF_GET)
                return NULL;
 
-       new_b = __alloc_buffer_wait(c);
+       new_b = __alloc_buffer_wait(c, nf);
+       if (!new_b)
+               return NULL;
 
        /*
         * We've had a period where the mutex was unlocked, so need to
@@ -899,10 +903,7 @@ static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
        b = __find(c, block);
        if (b) {
                __free_buffer_wake(new_b);
-               b->hold_count++;
-               __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
-                            test_bit(B_WRITING, &b->state));
-               return b;
+               goto found_buffer;
        }
 
        __check_watermark(c);
@@ -922,6 +923,24 @@ static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
        *need_submit = 1;
 
        return b;
+
+found_buffer:
+       if (nf == NF_PREFETCH)
+               return NULL;
+       /*
+        * Note: it is essential that we don't wait for the buffer to be
+        * read if dm_bufio_get function is used. Both dm_bufio_get and
+        * dm_bufio_prefetch can be used in the driver request routine.
+        * If the user called both dm_bufio_prefetch and dm_bufio_get on
+        * the same buffer, it would deadlock if we waited.
+        */
+       if (nf == NF_GET && unlikely(test_bit(B_READING, &b->state)))
+               return NULL;
+
+       b->hold_count++;
+       __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+                    test_bit(B_WRITING, &b->state));
+       return b;
 }
 
 /*
@@ -956,10 +975,10 @@ static void *new_read(struct dm_bufio_client *c, sector_t block,
        struct dm_buffer *b;
 
        dm_bufio_lock(c);
-       b = __bufio_new(c, block, nf, bp, &need_submit);
+       b = __bufio_new(c, block, nf, &need_submit);
        dm_bufio_unlock(c);
 
-       if (!b || IS_ERR(b))
+       if (!b)
                return b;
 
        if (need_submit)
@@ -1005,13 +1024,47 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
 }
 EXPORT_SYMBOL_GPL(dm_bufio_new);
 
+void dm_bufio_prefetch(struct dm_bufio_client *c,
+                      sector_t block, unsigned n_blocks)
+{
+       struct blk_plug plug;
+
+       blk_start_plug(&plug);
+       dm_bufio_lock(c);
+
+       for (; n_blocks--; block++) {
+               int need_submit;
+               struct dm_buffer *b;
+               b = __bufio_new(c, block, NF_PREFETCH, &need_submit);
+               if (unlikely(b != NULL)) {
+                       dm_bufio_unlock(c);
+
+                       if (need_submit)
+                               submit_io(b, READ, b->block, read_endio);
+                       dm_bufio_release(b);
+
+                       dm_bufio_cond_resched();
+
+                       if (!n_blocks)
+                               goto flush_plug;
+                       dm_bufio_lock(c);
+               }
+
+       }
+
+       dm_bufio_unlock(c);
+
+flush_plug:
+       blk_finish_plug(&plug);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_prefetch);
+
 void dm_bufio_release(struct dm_buffer *b)
 {
        struct dm_bufio_client *c = b->c;
 
        dm_bufio_lock(c);
 
-       BUG_ON(test_bit(B_READING, &b->state));
        BUG_ON(!b->hold_count);
 
        b->hold_count--;
@@ -1024,6 +1077,7 @@ void dm_bufio_release(struct dm_buffer *b)
                 * invalid buffer.
                 */
                if ((b->read_error || b->write_error) &&
+                   !test_bit(B_READING, &b->state) &&
                    !test_bit(B_WRITING, &b->state) &&
                    !test_bit(B_DIRTY, &b->state)) {
                        __unlink_buffer(b);
@@ -1041,6 +1095,8 @@ void dm_bufio_mark_buffer_dirty(struct dm_buffer *b)
 
        dm_bufio_lock(c);
 
+       BUG_ON(test_bit(B_READING, &b->state));
+
        if (!test_and_set_bit(B_DIRTY, &b->state))
                __relink_lru(b, LIST_DIRTY);
 
index 5c4c3a04e3810d76fc9b65277a99a3479cd3e23a..b142946a9e32ea23dcc241b5120ba00fe09e5287 100644 (file)
@@ -62,6 +62,14 @@ void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
 void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
                   struct dm_buffer **bp);
 
+/*
+ * Prefetch the specified blocks to the cache.
+ * The function starts to read the blocks and returns without waiting for
+ * I/O to finish.
+ */
+void dm_bufio_prefetch(struct dm_bufio_client *c,
+                      sector_t block, unsigned n_blocks);
+
 /*
  * Release a reference obtained with dm_bufio_{read,get,new}. The data
  * pointer and dm_buffer pointer is no longer valid after this call.
index db6b51639cee438e5b8ba0762c38105800d519b4..3f06df59fd824022fd80a9c77551178660909eb6 100644 (file)
@@ -176,7 +176,6 @@ struct crypt_config {
 
 #define MIN_IOS        16
 #define MIN_POOL_PAGES 32
-#define MIN_BIO_PAGES  8
 
 static struct kmem_cache *_crypt_io_pool;
 
@@ -848,12 +847,11 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
                }
 
                /*
-                * if additional pages cannot be allocated without waiting,
-                * return a partially allocated bio, the caller will then try
-                * to allocate additional bios while submitting this partial bio
+                * If additional pages cannot be allocated without waiting,
+                * return a partially-allocated bio.  The caller will then try
+                * to allocate more bios while submitting this partial bio.
                 */
-               if (i == (MIN_BIO_PAGES - 1))
-                       gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+               gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
 
                len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
 
@@ -1046,16 +1044,14 @@ static void kcryptd_queue_io(struct dm_crypt_io *io)
        queue_work(cc->io_queue, &io->work);
 }
 
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
-                                         int error, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
 {
        struct bio *clone = io->ctx.bio_out;
        struct crypt_config *cc = io->target->private;
 
-       if (unlikely(error < 0)) {
+       if (unlikely(io->error < 0)) {
                crypt_free_buffer_pages(cc, clone);
                bio_put(clone);
-               io->error = -EIO;
                crypt_dec_pending(io);
                return;
        }
@@ -1106,12 +1102,16 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
                sector += bio_sectors(clone);
 
                crypt_inc_pending(io);
+
                r = crypt_convert(cc, &io->ctx);
+               if (r < 0)
+                       io->error = -EIO;
+
                crypt_finished = atomic_dec_and_test(&io->ctx.pending);
 
                /* Encryption was already finished, submit io now */
                if (crypt_finished) {
-                       kcryptd_crypt_write_io_submit(io, r, 0);
+                       kcryptd_crypt_write_io_submit(io, 0);
 
                        /*
                         * If there was an error, do not try next fragments.
@@ -1162,11 +1162,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
        crypt_dec_pending(io);
 }
 
-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
 {
-       if (unlikely(error < 0))
-               io->error = -EIO;
-
        crypt_dec_pending(io);
 }
 
@@ -1181,9 +1178,11 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
                           io->sector);
 
        r = crypt_convert(cc, &io->ctx);
+       if (r < 0)
+               io->error = -EIO;
 
        if (atomic_dec_and_test(&io->ctx.pending))
-               kcryptd_crypt_read_done(io, r);
+               kcryptd_crypt_read_done(io);
 
        crypt_dec_pending(io);
 }
@@ -1204,15 +1203,18 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
        if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
                error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
 
+       if (error < 0)
+               io->error = -EIO;
+
        mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
 
        if (!atomic_dec_and_test(&ctx->pending))
                return;
 
        if (bio_data_dir(io->base_bio) == READ)
-               kcryptd_crypt_read_done(io, error);
+               kcryptd_crypt_read_done(io);
        else
-               kcryptd_crypt_write_io_submit(io, error, 1);
+               kcryptd_crypt_write_io_submit(io, 1);
 }
 
 static void kcryptd_crypt(struct work_struct *work)
@@ -1413,6 +1415,7 @@ static int crypt_ctr_cipher(struct dm_target *ti,
        char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount;
        char *cipher_api = NULL;
        int cpu, ret = -EINVAL;
+       char dummy;
 
        /* Convert to crypto api definition? */
        if (strchr(cipher_in, '(')) {
@@ -1434,7 +1437,7 @@ static int crypt_ctr_cipher(struct dm_target *ti,
 
        if (!keycount)
                cc->tfms_count = 1;
-       else if (sscanf(keycount, "%u", &cc->tfms_count) != 1 ||
+       else if (sscanf(keycount, "%u%c", &cc->tfms_count, &dummy) != 1 ||
                 !is_power_of_2(cc->tfms_count)) {
                ti->error = "Bad cipher key count specification";
                return -EINVAL;
@@ -1579,6 +1582,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        int ret;
        struct dm_arg_set as;
        const char *opt_string;
+       char dummy;
 
        static struct dm_arg _args[] = {
                {0, 1, "Invalid number of feature args"},
@@ -1636,7 +1640,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        ret = -EINVAL;
-       if (sscanf(argv[2], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid iv_offset sector";
                goto bad;
        }
@@ -1647,7 +1651,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad;
        }
 
-       if (sscanf(argv[4], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index f18375dcedd99e0a878eff957c73e5f9d0ffd73a..2dc22dddb2ae31abe4b5bb2371dfb8eaedfeec73 100644 (file)
@@ -131,6 +131,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        struct delay_c *dc;
        unsigned long long tmpll;
+       char dummy;
 
        if (argc != 3 && argc != 6) {
                ti->error = "requires exactly 3 or 6 arguments";
@@ -145,13 +146,13 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        dc->reads = dc->writes = 0;
 
-       if (sscanf(argv[1], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid device sector";
                goto bad;
        }
        dc->start_read = tmpll;
 
-       if (sscanf(argv[2], "%u", &dc->read_delay) != 1) {
+       if (sscanf(argv[2], "%u%c", &dc->read_delay, &dummy) != 1) {
                ti->error = "Invalid delay";
                goto bad;
        }
@@ -166,13 +167,13 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        if (argc == 3)
                goto out;
 
-       if (sscanf(argv[4], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid write device sector";
                goto bad_dev_read;
        }
        dc->start_write = tmpll;
 
-       if (sscanf(argv[5], "%u", &dc->write_delay) != 1) {
+       if (sscanf(argv[5], "%u%c", &dc->write_delay, &dummy) != 1) {
                ti->error = "Invalid write delay";
                goto bad_dev_read;
        }
index 042e71996569b963a6d9ec1addd4ae5aab97a23c..aa70f7d43a1ab87750cee933d244eb098cb8d92b 100644 (file)
@@ -283,7 +283,7 @@ int dm_exception_store_init(void)
        return 0;
 
 persistent_fail:
-       dm_persistent_snapshot_exit();
+       dm_transient_snapshot_exit();
 transient_fail:
        return r;
 }
index b280c433e4a08196c0fe3d5166d9fb9f0879704f..ac49c01f1a44bc6264ab50fcb1f7ba34bf271346 100644 (file)
@@ -160,6 +160,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        unsigned long long tmpll;
        struct dm_arg_set as;
        const char *devname;
+       char dummy;
 
        as.argc = argc;
        as.argv = argv;
@@ -178,7 +179,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        devname = dm_shift_arg(&as);
 
-       if (sscanf(dm_shift_arg(&as), "%llu", &tmpll) != 1) {
+       if (sscanf(dm_shift_arg(&as), "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index 1ce84ed0b765a889b74b94674da2aff4ffe0fd1c..a1a3e6df17b82624490952b0c91f94a9ea1e1f86 100644 (file)
@@ -880,6 +880,7 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
        struct hd_geometry geometry;
        unsigned long indata[4];
        char *geostr = (char *) param + param->data_start;
+       char dummy;
 
        md = find_device(param);
        if (!md)
@@ -891,8 +892,8 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
                goto out;
        }
 
-       x = sscanf(geostr, "%lu %lu %lu %lu", indata,
-                  indata + 1, indata + 2, indata + 3);
+       x = sscanf(geostr, "%lu %lu %lu %lu%c", indata,
+                  indata + 1, indata + 2, indata + 3, &dummy);
 
        if (x != 4) {
                DMWARN("Unable to interpret geometry settings.");
index 9728839f844a8b71a34c04b7317a9dc1fe1497ba..3639eeab60421fb1829c2f70ee7bd7e193267463 100644 (file)
@@ -29,6 +29,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        struct linear_c *lc;
        unsigned long long tmp;
+       char dummy;
 
        if (argc != 2) {
                ti->error = "Invalid argument count";
@@ -41,7 +42,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                return -ENOMEM;
        }
 
-       if (sscanf(argv[1], "%llu", &tmp) != 1) {
+       if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
                ti->error = "dm-linear: Invalid device sector";
                goto bad;
        }
index 3b52bb72bd1f0cb8717798c121008a76784b9aa0..65ebaebf502bdbc6e35f0cec1272589e2e5e000e 100644 (file)
@@ -369,6 +369,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
        unsigned int region_count;
        size_t bitset_size, buf_size;
        int r;
+       char dummy;
 
        if (argc < 1 || argc > 2) {
                DMWARN("wrong number of arguments to dirty region log");
@@ -387,7 +388,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
                }
        }
 
-       if (sscanf(argv[0], "%u", &region_size) != 1 ||
+       if (sscanf(argv[0], "%u%c", &region_size, &dummy) != 1 ||
            !_check_region_size(ti, region_size)) {
                DMWARN("invalid region size %s", argv[0]);
                return -EINVAL;
index 801d92d237cfc316ee81c08ab4c261f7113f2690..922a3385eead41be43bafeac56a4e417ad7b919d 100644 (file)
@@ -226,6 +226,27 @@ static void free_multipath(struct multipath *m)
        kfree(m);
 }
 
+static int set_mapinfo(struct multipath *m, union map_info *info)
+{
+       struct dm_mpath_io *mpio;
+
+       mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
+       if (!mpio)
+               return -ENOMEM;
+
+       memset(mpio, 0, sizeof(*mpio));
+       info->ptr = mpio;
+
+       return 0;
+}
+
+static void clear_mapinfo(struct multipath *m, union map_info *info)
+{
+       struct dm_mpath_io *mpio = info->ptr;
+
+       info->ptr = NULL;
+       mempool_free(mpio, m->mpio_pool);
+}
 
 /*-----------------------------------------------
  * Path selection
@@ -341,13 +362,14 @@ static int __must_push_back(struct multipath *m)
 }
 
 static int map_io(struct multipath *m, struct request *clone,
-                 struct dm_mpath_io *mpio, unsigned was_queued)
+                 union map_info *map_context, unsigned was_queued)
 {
        int r = DM_MAPIO_REMAPPED;
        size_t nr_bytes = blk_rq_bytes(clone);
        unsigned long flags;
        struct pgpath *pgpath;
        struct block_device *bdev;
+       struct dm_mpath_io *mpio = map_context->ptr;
 
        spin_lock_irqsave(&m->lock, flags);
 
@@ -423,7 +445,6 @@ static void dispatch_queued_ios(struct multipath *m)
 {
        int r;
        unsigned long flags;
-       struct dm_mpath_io *mpio;
        union map_info *info;
        struct request *clone, *n;
        LIST_HEAD(cl);
@@ -436,16 +457,15 @@ static void dispatch_queued_ios(struct multipath *m)
                list_del_init(&clone->queuelist);
 
                info = dm_get_rq_mapinfo(clone);
-               mpio = info->ptr;
 
-               r = map_io(m, clone, mpio, 1);
+               r = map_io(m, clone, info, 1);
                if (r < 0) {
-                       mempool_free(mpio, m->mpio_pool);
+                       clear_mapinfo(m, info);
                        dm_kill_unmapped_request(clone, r);
                } else if (r == DM_MAPIO_REMAPPED)
                        dm_dispatch_request(clone);
                else if (r == DM_MAPIO_REQUEUE) {
-                       mempool_free(mpio, m->mpio_pool);
+                       clear_mapinfo(m, info);
                        dm_requeue_unmapped_request(clone);
                }
        }
@@ -908,20 +928,16 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
                         union map_info *map_context)
 {
        int r;
-       struct dm_mpath_io *mpio;
        struct multipath *m = (struct multipath *) ti->private;
 
-       mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
-       if (!mpio)
+       if (set_mapinfo(m, map_context) < 0)
                /* ENOMEM, requeue */
                return DM_MAPIO_REQUEUE;
-       memset(mpio, 0, sizeof(*mpio));
 
-       map_context->ptr = mpio;
        clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
-       r = map_io(m, clone, mpio, 0);
+       r = map_io(m, clone, map_context, 0);
        if (r < 0 || r == DM_MAPIO_REQUEUE)
-               mempool_free(mpio, m->mpio_pool);
+               clear_mapinfo(m, map_context);
 
        return r;
 }
@@ -1054,8 +1070,9 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
        struct priority_group *pg;
        unsigned pgnum;
        unsigned long flags;
+       char dummy;
 
-       if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+       if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
            (pgnum > m->nr_priority_groups)) {
                DMWARN("invalid PG number supplied to switch_pg_num");
                return -EINVAL;
@@ -1085,8 +1102,9 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
 {
        struct priority_group *pg;
        unsigned pgnum;
+       char dummy;
 
-       if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+       if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
            (pgnum > m->nr_priority_groups)) {
                DMWARN("invalid PG number supplied to bypass_pg");
                return -EINVAL;
@@ -1261,13 +1279,15 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
        struct path_selector *ps;
        int r;
 
+       BUG_ON(!mpio);
+
        r  = do_end_io(m, clone, error, mpio);
        if (pgpath) {
                ps = &pgpath->pg->ps;
                if (ps->type->end_io)
                        ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
        }
-       mempool_free(mpio, m->mpio_pool);
+       clear_mapinfo(m, map_context);
 
        return r;
 }
index 03a837aa5ce64ebd38af21d324e77b14cd5f4434..3941fae0de9fd79f875f5ea32ce14b03cb76d8aa 100644 (file)
@@ -112,6 +112,7 @@ static int ql_add_path(struct path_selector *ps, struct dm_path *path,
        struct selector *s = ps->context;
        struct path_info *pi;
        unsigned repeat_count = QL_MIN_IO;
+       char dummy;
 
        /*
         * Arguments: [<repeat_count>]
@@ -123,7 +124,7 @@ static int ql_add_path(struct path_selector *ps, struct dm_path *path,
                return -EINVAL;
        }
 
-       if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+       if ((argc == 1) && (sscanf(argv[0], "%u%c", &repeat_count, &dummy) != 1)) {
                *error = "queue-length ps: invalid repeat count";
                return -EINVAL;
        }
index c5a875d7b8827833b70eb76a818ee9bf55073f53..b0ba52459ed7381d4a802acb94e69df02f979149 100644 (file)
@@ -604,7 +604,9 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
                return 0;
 
        if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) {
-               DMERR("Failed to read device superblock");
+               DMERR("Failed to read superblock of device at position %d",
+                     rdev->raid_disk);
+               set_bit(Faulty, &rdev->flags);
                return -EINVAL;
        }
 
@@ -855,9 +857,25 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 {
        int ret;
+       unsigned redundancy = 0;
+       struct raid_dev *dev;
        struct md_rdev *rdev, *freshest;
        struct mddev *mddev = &rs->md;
 
+       switch (rs->raid_type->level) {
+       case 1:
+               redundancy = rs->md.raid_disks - 1;
+               break;
+       case 4:
+       case 5:
+       case 6:
+               redundancy = rs->raid_type->parity_devs;
+               break;
+       default:
+               ti->error = "Unknown RAID type";
+               return -EINVAL;
+       }
+
        freshest = NULL;
        rdev_for_each(rdev, mddev) {
                if (!rdev->meta_bdev)
@@ -872,6 +890,37 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
                case 0:
                        break;
                default:
+                       dev = container_of(rdev, struct raid_dev, rdev);
+                       if (redundancy--) {
+                               if (dev->meta_dev)
+                                       dm_put_device(ti, dev->meta_dev);
+
+                               dev->meta_dev = NULL;
+                               rdev->meta_bdev = NULL;
+
+                               if (rdev->sb_page)
+                                       put_page(rdev->sb_page);
+
+                               rdev->sb_page = NULL;
+
+                               rdev->sb_loaded = 0;
+
+                               /*
+                                * We might be able to salvage the data device
+                                * even though the meta device has failed.  For
+                                * now, we behave as though '- -' had been
+                                * set for this device in the table.
+                                */
+                               if (dev->data_dev)
+                                       dm_put_device(ti, dev->data_dev);
+
+                               dev->data_dev = NULL;
+                               rdev->bdev = NULL;
+
+                               list_del(&rdev->same_set);
+
+                               continue;
+                       }
                        ti->error = "Failed to load superblock";
                        return ret;
                }
@@ -1214,7 +1263,7 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 1, 0},
+       .version = {1, 2, 0},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
index 9bfd057be6869dff2aba03a498b20e1c148ba4c8..d039de8322f0a314fca492df4b932289d9033e0d 100644 (file)
@@ -924,8 +924,9 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
                      unsigned int mirror, char **argv)
 {
        unsigned long long offset;
+       char dummy;
 
-       if (sscanf(argv[1], "%llu", &offset) != 1) {
+       if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1) {
                ti->error = "Invalid offset";
                return -EINVAL;
        }
@@ -953,13 +954,14 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
 {
        unsigned param_count;
        struct dm_dirty_log *dl;
+       char dummy;
 
        if (argc < 2) {
                ti->error = "Insufficient mirror log arguments";
                return NULL;
        }
 
-       if (sscanf(argv[1], "%u", &param_count) != 1) {
+       if (sscanf(argv[1], "%u%c", &param_count, &dummy) != 1) {
                ti->error = "Invalid mirror log argument count";
                return NULL;
        }
@@ -986,13 +988,14 @@ static int parse_features(struct mirror_set *ms, unsigned argc, char **argv,
 {
        unsigned num_features;
        struct dm_target *ti = ms->ti;
+       char dummy;
 
        *args_used = 0;
 
        if (!argc)
                return 0;
 
-       if (sscanf(argv[0], "%u", &num_features) != 1) {
+       if (sscanf(argv[0], "%u%c", &num_features, &dummy) != 1) {
                ti->error = "Invalid number of features";
                return -EINVAL;
        }
@@ -1036,6 +1039,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        unsigned int nr_mirrors, m, args_used;
        struct mirror_set *ms;
        struct dm_dirty_log *dl;
+       char dummy;
 
        dl = create_dirty_log(ti, argc, argv, &args_used);
        if (!dl)
@@ -1044,7 +1048,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        argv += args_used;
        argc -= args_used;
 
-       if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
+       if (!argc || sscanf(argv[0], "%u%c", &nr_mirrors, &dummy) != 1 ||
            nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) {
                ti->error = "Invalid number of mirrors";
                dm_dirty_log_destroy(dl);
index 27f1d423b76c0582f77001a1265526fc29db2a47..6ab1192cdd5fcf766f67b76ff7a6678db4fab8a7 100644 (file)
@@ -114,6 +114,7 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
        struct selector *s = (struct selector *) ps->context;
        struct path_info *pi;
        unsigned repeat_count = RR_MIN_IO;
+       char dummy;
 
        if (argc > 1) {
                *error = "round-robin ps: incorrect number of arguments";
@@ -121,7 +122,7 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
        }
 
        /* First path argument is number of I/Os before switching path */
-       if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+       if ((argc == 1) && (sscanf(argv[0], "%u%c", &repeat_count, &dummy) != 1)) {
                *error = "round-robin ps: invalid repeat count";
                return -EINVAL;
        }
index 59883bd78214b0428a819ee19d397f460bfc6d8b..9df8f6bd64181fd9d4b1f1eb425d247b501fcb66 100644 (file)
@@ -110,6 +110,7 @@ static int st_add_path(struct path_selector *ps, struct dm_path *path,
        struct path_info *pi;
        unsigned repeat_count = ST_MIN_IO;
        unsigned relative_throughput = 1;
+       char dummy;
 
        /*
         * Arguments: [<repeat_count> [<relative_throughput>]]
@@ -128,13 +129,13 @@ static int st_add_path(struct path_selector *ps, struct dm_path *path,
                return -EINVAL;
        }
 
-       if (argc && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+       if (argc && (sscanf(argv[0], "%u%c", &repeat_count, &dummy) != 1)) {
                *error = "service-time ps: invalid repeat count";
                return -EINVAL;
        }
 
        if ((argc == 2) &&
-           (sscanf(argv[1], "%u", &relative_throughput) != 1 ||
+           (sscanf(argv[1], "%u%c", &relative_throughput, &dummy) != 1 ||
             relative_throughput > ST_MAX_RELATIVE_THROUGHPUT)) {
                *error = "service-time ps: invalid relative_throughput value";
                return -EINVAL;
index 3d80cf0c152d1b4fedd46a0b67773842218a326c..35c94ff24ad5867917ed715a8ce387fbb8d3b150 100644 (file)
@@ -75,8 +75,9 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
                      unsigned int stripe, char **argv)
 {
        unsigned long long start;
+       char dummy;
 
-       if (sscanf(argv[1], "%llu", &start) != 1)
+       if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1)
                return -EINVAL;
 
        if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
index 63cc54289afff481c1d4ce8a9cc2e6749de8b5de..2e227fbf1622c075c6fc543f5b2d30fb2bf7dbd7 100644 (file)
@@ -268,8 +268,7 @@ void dm_table_destroy(struct dm_table *t)
        vfree(t->highs);
 
        /* free the device list */
-       if (t->devices.next != &t->devices)
-               free_devices(&t->devices);
+       free_devices(&t->devices);
 
        dm_free_md_mempools(t->mempools);
 
@@ -464,10 +463,11 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
        struct dm_dev_internal *dd;
        unsigned int major, minor;
        struct dm_table *t = ti->table;
+       char dummy;
 
        BUG_ON(!t);
 
-       if (sscanf(path, "%u:%u", &major, &minor) == 2) {
+       if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
                /* Extract the major/minor numbers */
                dev = MKDEV(major, minor);
                if (MAJOR(dev) != major || MINOR(dev) != minor)
@@ -842,9 +842,10 @@ static int validate_next_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
                             unsigned *value, char **error, unsigned grouped)
 {
        const char *arg_str = dm_shift_arg(arg_set);
+       char dummy;
 
        if (!arg_str ||
-           (sscanf(arg_str, "%u", value) != 1) ||
+           (sscanf(arg_str, "%u%c", value, &dummy) != 1) ||
            (*value < arg->min) ||
            (*value > arg->max) ||
            (grouped && arg_set->argc < *value)) {
index 237571af77fdfcf552b7061fa13ff291514c86b7..737d38865b693fb0288306477587f4e0d52f6cfa 100644 (file)
@@ -614,7 +614,7 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
        if (r < 0)
                goto out;
 
-       r = dm_sm_root_size(pmd->metadata_sm, &data_len);
+       r = dm_sm_root_size(pmd->data_sm, &data_len);
        if (r < 0)
                goto out;
 
@@ -713,6 +713,9 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
        if (r)
                goto bad;
 
+       if (bdev_size > THIN_METADATA_MAX_SECTORS)
+               bdev_size = THIN_METADATA_MAX_SECTORS;
+
        disk_super = dm_block_data(sblock);
        disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
        disk_super->version = cpu_to_le32(THIN_VERSION);
index 859c16896877795732ad89df1b854bd2242d019b..ed4725e67c96fbae52f1ce48c28d79f0a02075a4 100644 (file)
 
 #define THIN_METADATA_BLOCK_SIZE 4096
 
+/*
+ * The metadata device is currently limited in size.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about 16k metadata blocks.
+ */
+#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+
+/*
+ * A metadata device larger than 16GB triggers a warning.
+ */
+#define THIN_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT))
+
 /*----------------------------------------------------------------*/
 
 struct dm_pool_metadata;
index c3087575fef0ffe5330c261a721abddef3f6771e..213ae32a0fc4f7eadacb923a5f1f2ac69163f5c7 100644 (file)
@@ -23,6 +23,7 @@
 #define DEFERRED_SET_SIZE 64
 #define MAPPING_POOL_SIZE 1024
 #define PRISON_CELLS 1024
+#define COMMIT_PERIOD HZ
 
 /*
  * The block size of the device holding pool data must be
 #define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
 #define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
 
-/*
- * The metadata device is currently limited in size.  The limitation is
- * checked lower down in dm-space-map-metadata, but we also check it here
- * so we can fail early.
- *
- * We have one block of index, which can hold 255 index entries.  Each
- * index entry contains allocation info about 16k metadata blocks.
- */
-#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
-
 /*
  * Device id is restricted to 24 bits.
  */
@@ -72,7 +63,7 @@
  * missed out if the io covers the block. (schedule_copy).
  *
  * iv) insert the new mapping into the origin's btree
- * (process_prepared_mappings).  This act of inserting breaks some
+ * (process_prepared_mapping).  This act of inserting breaks some
  * sharing of btree nodes between the two devices.  Breaking sharing only
  * effects the btree of that specific device.  Btrees for the other
  * devices that share the block never change.  The btree for the origin
@@ -124,7 +115,7 @@ struct cell {
        struct hlist_node list;
        struct bio_prison *prison;
        struct cell_key key;
-       unsigned count;
+       struct bio *holder;
        struct bio_list bios;
 };
 
@@ -220,54 +211,59 @@ static struct cell *__search_bucket(struct hlist_head *bucket,
  * This may block if a new cell needs allocating.  You must ensure that
  * cells will be unlocked even if the calling thread is blocked.
  *
- * Returns the number of entries in the cell prior to the new addition
- * or < 0 on failure.
+ * Returns 1 if the cell was already held, 0 if @inmate is the new holder.
  */
 static int bio_detain(struct bio_prison *prison, struct cell_key *key,
                      struct bio *inmate, struct cell **ref)
 {
-       int r;
+       int r = 1;
        unsigned long flags;
        uint32_t hash = hash_key(prison, key);
-       struct cell *uninitialized_var(cell), *cell2 = NULL;
+       struct cell *cell, *cell2;
 
        BUG_ON(hash > prison->nr_buckets);
 
        spin_lock_irqsave(&prison->lock, flags);
+
        cell = __search_bucket(prison->cells + hash, key);
+       if (cell) {
+               bio_list_add(&cell->bios, inmate);
+               goto out;
+       }
 
-       if (!cell) {
-               /*
-                * Allocate a new cell
-                */
-               spin_unlock_irqrestore(&prison->lock, flags);
-               cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
-               spin_lock_irqsave(&prison->lock, flags);
+       /*
+        * Allocate a new cell
+        */
+       spin_unlock_irqrestore(&prison->lock, flags);
+       cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+       spin_lock_irqsave(&prison->lock, flags);
 
-               /*
-                * We've been unlocked, so we have to double check that
-                * nobody else has inserted this cell in the meantime.
-                */
-               cell = __search_bucket(prison->cells + hash, key);
+       /*
+        * We've been unlocked, so we have to double check that
+        * nobody else has inserted this cell in the meantime.
+        */
+       cell = __search_bucket(prison->cells + hash, key);
+       if (cell) {
+               mempool_free(cell2, prison->cell_pool);
+               bio_list_add(&cell->bios, inmate);
+               goto out;
+       }
 
-               if (!cell) {
-                       cell = cell2;
-                       cell2 = NULL;
+       /*
+        * Use new cell.
+        */
+       cell = cell2;
 
-                       cell->prison = prison;
-                       memcpy(&cell->key, key, sizeof(cell->key));
-                       cell->count = 0;
-                       bio_list_init(&cell->bios);
-                       hlist_add_head(&cell->list, prison->cells + hash);
-               }
-       }
+       cell->prison = prison;
+       memcpy(&cell->key, key, sizeof(cell->key));
+       cell->holder = inmate;
+       bio_list_init(&cell->bios);
+       hlist_add_head(&cell->list, prison->cells + hash);
 
-       r = cell->count++;
-       bio_list_add(&cell->bios, inmate);
-       spin_unlock_irqrestore(&prison->lock, flags);
+       r = 0;
 
-       if (cell2)
-               mempool_free(cell2, prison->cell_pool);
+out:
+       spin_unlock_irqrestore(&prison->lock, flags);
 
        *ref = cell;
 
@@ -283,8 +279,8 @@ static void __cell_release(struct cell *cell, struct bio_list *inmates)
 
        hlist_del(&cell->list);
 
-       if (inmates)
-               bio_list_merge(inmates, &cell->bios);
+       bio_list_add(inmates, cell->holder);
+       bio_list_merge(inmates, &cell->bios);
 
        mempool_free(cell, prison->cell_pool);
 }
@@ -305,22 +301,44 @@ static void cell_release(struct cell *cell, struct bio_list *bios)
  * bio may be in the cell.  This function releases the cell, and also does
  * a sanity check.
  */
+static void __cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+       hlist_del(&cell->list);
+       BUG_ON(cell->holder != bio);
+       BUG_ON(!bio_list_empty(&cell->bios));
+}
+
 static void cell_release_singleton(struct cell *cell, struct bio *bio)
 {
-       struct bio_prison *prison = cell->prison;
-       struct bio_list bios;
-       struct bio *b;
        unsigned long flags;
-
-       bio_list_init(&bios);
+       struct bio_prison *prison = cell->prison;
 
        spin_lock_irqsave(&prison->lock, flags);
-       __cell_release(cell, &bios);
+       __cell_release_singleton(cell, bio);
        spin_unlock_irqrestore(&prison->lock, flags);
+}
+
+/*
+ * Sometimes we don't want the holder, just the additional bios.
+ */
+static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
+{
+       struct bio_prison *prison = cell->prison;
+
+       hlist_del(&cell->list);
+       bio_list_merge(inmates, &cell->bios);
 
-       b = bio_list_pop(&bios);
-       BUG_ON(b != bio);
-       BUG_ON(!bio_list_empty(&bios));
+       mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
+{
+       unsigned long flags;
+       struct bio_prison *prison = cell->prison;
+
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release_no_holder(cell, inmates);
+       spin_unlock_irqrestore(&prison->lock, flags);
 }
 
 static void cell_error(struct cell *cell)
@@ -471,6 +489,13 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
  * devices.
  */
 struct new_mapping;
+
+struct pool_features {
+       unsigned zero_new_blocks:1;
+       unsigned discard_enabled:1;
+       unsigned discard_passdown:1;
+};
+
 struct pool {
        struct list_head list;
        struct dm_target *ti;   /* Only set if a pool target is bound */
@@ -484,7 +509,7 @@ struct pool {
        dm_block_t offset_mask;
        dm_block_t low_water_blocks;
 
-       unsigned zero_new_blocks:1;
+       struct pool_features pf;
        unsigned low_water_triggered:1; /* A dm event has been sent */
        unsigned no_free_space:1;       /* A -ENOSPC warning has been issued */
 
@@ -493,17 +518,21 @@ struct pool {
 
        struct workqueue_struct *wq;
        struct work_struct worker;
+       struct delayed_work waker;
 
        unsigned ref_count;
+       unsigned long last_commit_jiffies;
 
        spinlock_t lock;
        struct bio_list deferred_bios;
        struct bio_list deferred_flush_bios;
        struct list_head prepared_mappings;
+       struct list_head prepared_discards;
 
        struct bio_list retry_on_resume_list;
 
-       struct deferred_set ds; /* FIXME: move to thin_c */
+       struct deferred_set shared_read_ds;
+       struct deferred_set all_io_ds;
 
        struct new_mapping *next_mapping;
        mempool_t *mapping_pool;
@@ -521,7 +550,7 @@ struct pool_c {
        struct dm_target_callbacks callbacks;
 
        dm_block_t low_water_blocks;
-       unsigned zero_new_blocks:1;
+       struct pool_features pf;
 };
 
 /*
@@ -529,6 +558,7 @@ struct pool_c {
  */
 struct thin_c {
        struct dm_dev *pool_dev;
+       struct dm_dev *origin_dev;
        dm_thin_id dev_id;
 
        struct pool *pool;
@@ -597,6 +627,13 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev
 
 /*----------------------------------------------------------------*/
 
+struct endio_hook {
+       struct thin_c *tc;
+       struct deferred_entry *shared_read_entry;
+       struct deferred_entry *all_io_entry;
+       struct new_mapping *overwrite_mapping;
+};
+
 static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
 {
        struct bio *bio;
@@ -607,7 +644,8 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
        bio_list_init(master);
 
        while ((bio = bio_list_pop(&bios))) {
-               if (dm_get_mapinfo(bio)->ptr == tc)
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               if (h->tc == tc)
                        bio_endio(bio, DM_ENDIO_REQUEUE);
                else
                        bio_list_add(master, bio);
@@ -646,14 +684,16 @@ static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
                (bio->bi_sector & pool->offset_mask);
 }
 
-static void remap_and_issue(struct thin_c *tc, struct bio *bio,
-                           dm_block_t block)
+static void remap_to_origin(struct thin_c *tc, struct bio *bio)
+{
+       bio->bi_bdev = tc->origin_dev->bdev;
+}
+
+static void issue(struct thin_c *tc, struct bio *bio)
 {
        struct pool *pool = tc->pool;
        unsigned long flags;
 
-       remap(tc, bio, block);
-
        /*
         * Batch together any FUA/FLUSH bios we find and then issue
         * a single commit for them in process_deferred_bios().
@@ -666,6 +706,19 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio,
                generic_make_request(bio);
 }
 
+static void remap_to_origin_and_issue(struct thin_c *tc, struct bio *bio)
+{
+       remap_to_origin(tc, bio);
+       issue(tc, bio);
+}
+
+static void remap_and_issue(struct thin_c *tc, struct bio *bio,
+                           dm_block_t block)
+{
+       remap(tc, bio, block);
+       issue(tc, bio);
+}
+
 /*
  * wake_worker() is used when new work is queued and when pool_resume is
  * ready to continue deferred IO processing.
@@ -680,21 +733,17 @@ static void wake_worker(struct pool *pool)
 /*
  * Bio endio functions.
  */
-struct endio_hook {
-       struct thin_c *tc;
-       bio_end_io_t *saved_bi_end_io;
-       struct deferred_entry *entry;
-};
-
 struct new_mapping {
        struct list_head list;
 
-       int prepared;
+       unsigned quiesced:1;
+       unsigned prepared:1;
+       unsigned pass_discard:1;
 
        struct thin_c *tc;
        dm_block_t virt_block;
        dm_block_t data_block;
-       struct cell *cell;
+       struct cell *cell, *cell2;
        int err;
 
        /*
@@ -711,7 +760,7 @@ static void __maybe_add_mapping(struct new_mapping *m)
 {
        struct pool *pool = m->tc->pool;
 
-       if (list_empty(&m->list) && m->prepared) {
+       if (m->quiesced && m->prepared) {
                list_add(&m->list, &pool->prepared_mappings);
                wake_worker(pool);
        }
@@ -734,7 +783,8 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
 static void overwrite_endio(struct bio *bio, int err)
 {
        unsigned long flags;
-       struct new_mapping *m = dm_get_mapinfo(bio)->ptr;
+       struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+       struct new_mapping *m = h->overwrite_mapping;
        struct pool *pool = m->tc->pool;
 
        m->err = err;
@@ -745,31 +795,6 @@ static void overwrite_endio(struct bio *bio, int err)
        spin_unlock_irqrestore(&pool->lock, flags);
 }
 
-static void shared_read_endio(struct bio *bio, int err)
-{
-       struct list_head mappings;
-       struct new_mapping *m, *tmp;
-       struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
-       unsigned long flags;
-       struct pool *pool = h->tc->pool;
-
-       bio->bi_end_io = h->saved_bi_end_io;
-       bio_endio(bio, err);
-
-       INIT_LIST_HEAD(&mappings);
-       ds_dec(h->entry, &mappings);
-
-       spin_lock_irqsave(&pool->lock, flags);
-       list_for_each_entry_safe(m, tmp, &mappings, list) {
-               list_del(&m->list);
-               INIT_LIST_HEAD(&m->list);
-               __maybe_add_mapping(m);
-       }
-       spin_unlock_irqrestore(&pool->lock, flags);
-
-       mempool_free(h, pool->endio_hook_pool);
-}
-
 /*----------------------------------------------------------------*/
 
 /*
@@ -800,21 +825,16 @@ static void cell_defer(struct thin_c *tc, struct cell *cell,
  * Same as cell_defer above, except it omits one particular detainee,
  * a write bio that covers the block and has already been processed.
  */
-static void cell_defer_except(struct thin_c *tc, struct cell *cell,
-                             struct bio *exception)
+static void cell_defer_except(struct thin_c *tc, struct cell *cell)
 {
        struct bio_list bios;
-       struct bio *bio;
        struct pool *pool = tc->pool;
        unsigned long flags;
 
        bio_list_init(&bios);
-       cell_release(cell, &bios);
 
        spin_lock_irqsave(&pool->lock, flags);
-       while ((bio = bio_list_pop(&bios)))
-               if (bio != exception)
-                       bio_list_add(&pool->deferred_bios, bio);
+       cell_release_no_holder(cell, &pool->deferred_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
        wake_worker(pool);
@@ -854,7 +874,7 @@ static void process_prepared_mapping(struct new_mapping *m)
         * the bios in the cell.
         */
        if (bio) {
-               cell_defer_except(tc, m->cell, bio);
+               cell_defer_except(tc, m->cell);
                bio_endio(bio, 0);
        } else
                cell_defer(tc, m->cell, m->data_block);
@@ -863,7 +883,30 @@ static void process_prepared_mapping(struct new_mapping *m)
        mempool_free(m, tc->pool->mapping_pool);
 }
 
-static void process_prepared_mappings(struct pool *pool)
+static void process_prepared_discard(struct new_mapping *m)
+{
+       int r;
+       struct thin_c *tc = m->tc;
+
+       r = dm_thin_remove_block(tc->td, m->virt_block);
+       if (r)
+               DMERR("dm_thin_remove_block() failed");
+
+       /*
+        * Pass the discard down to the underlying device?
+        */
+       if (m->pass_discard)
+               remap_and_issue(tc, m->bio, m->data_block);
+       else
+               bio_endio(m->bio, 0);
+
+       cell_defer_except(tc, m->cell);
+       cell_defer_except(tc, m->cell2);
+       mempool_free(m, tc->pool->mapping_pool);
+}
+
+static void process_prepared(struct pool *pool, struct list_head *head,
+                            void (*fn)(struct new_mapping *))
 {
        unsigned long flags;
        struct list_head maps;
@@ -871,21 +914,27 @@ static void process_prepared_mappings(struct pool *pool)
 
        INIT_LIST_HEAD(&maps);
        spin_lock_irqsave(&pool->lock, flags);
-       list_splice_init(&pool->prepared_mappings, &maps);
+       list_splice_init(head, &maps);
        spin_unlock_irqrestore(&pool->lock, flags);
 
        list_for_each_entry_safe(m, tmp, &maps, list)
-               process_prepared_mapping(m);
+               fn(m);
 }
 
 /*
  * Deferred bio jobs.
  */
-static int io_overwrites_block(struct pool *pool, struct bio *bio)
+static int io_overlaps_block(struct pool *pool, struct bio *bio)
 {
-       return ((bio_data_dir(bio) == WRITE) &&
-               !(bio->bi_sector & pool->offset_mask)) &&
+       return !(bio->bi_sector & pool->offset_mask) &&
                (bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+
+}
+
+static int io_overwrites_block(struct pool *pool, struct bio *bio)
+{
+       return (bio_data_dir(bio) == WRITE) &&
+               io_overlaps_block(pool, bio);
 }
 
 static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
@@ -917,7 +966,8 @@ static struct new_mapping *get_next_mapping(struct pool *pool)
 }
 
 static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
-                         dm_block_t data_origin, dm_block_t data_dest,
+                         struct dm_dev *origin, dm_block_t data_origin,
+                         dm_block_t data_dest,
                          struct cell *cell, struct bio *bio)
 {
        int r;
@@ -925,6 +975,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        struct new_mapping *m = get_next_mapping(pool);
 
        INIT_LIST_HEAD(&m->list);
+       m->quiesced = 0;
        m->prepared = 0;
        m->tc = tc;
        m->virt_block = virt_block;
@@ -933,7 +984,8 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        m->err = 0;
        m->bio = NULL;
 
-       ds_add_work(&pool->ds, &m->list);
+       if (!ds_add_work(&pool->shared_read_ds, &m->list))
+               m->quiesced = 1;
 
        /*
         * IO to pool_dev remaps to the pool target's data_dev.
@@ -942,14 +994,15 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
         * bio immediately. Otherwise we use kcopyd to clone the data first.
         */
        if (io_overwrites_block(pool, bio)) {
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               h->overwrite_mapping = m;
                m->bio = bio;
                save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
-               dm_get_mapinfo(bio)->ptr = m;
                remap_and_issue(tc, bio, data_dest);
        } else {
                struct dm_io_region from, to;
 
-               from.bdev = tc->pool_dev->bdev;
+               from.bdev = origin->bdev;
                from.sector = data_origin * pool->sectors_per_block;
                from.count = pool->sectors_per_block;
 
@@ -967,6 +1020,22 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        }
 }
 
+static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block,
+                                  dm_block_t data_origin, dm_block_t data_dest,
+                                  struct cell *cell, struct bio *bio)
+{
+       schedule_copy(tc, virt_block, tc->pool_dev,
+                     data_origin, data_dest, cell, bio);
+}
+
+static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block,
+                                  dm_block_t data_dest,
+                                  struct cell *cell, struct bio *bio)
+{
+       schedule_copy(tc, virt_block, tc->origin_dev,
+                     virt_block, data_dest, cell, bio);
+}
+
 static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
                          dm_block_t data_block, struct cell *cell,
                          struct bio *bio)
@@ -975,6 +1044,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
        struct new_mapping *m = get_next_mapping(pool);
 
        INIT_LIST_HEAD(&m->list);
+       m->quiesced = 1;
        m->prepared = 0;
        m->tc = tc;
        m->virt_block = virt_block;
@@ -988,13 +1058,14 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
         * zeroing pre-existing data, we can issue the bio immediately.
         * Otherwise we use kcopyd to zero the data first.
         */
-       if (!pool->zero_new_blocks)
+       if (!pool->pf.zero_new_blocks)
                process_prepared_mapping(m);
 
        else if (io_overwrites_block(pool, bio)) {
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               h->overwrite_mapping = m;
                m->bio = bio;
                save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
-               dm_get_mapinfo(bio)->ptr = m;
                remap_and_issue(tc, bio, data_block);
 
        } else {
@@ -1081,7 +1152,8 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
  */
 static void retry_on_resume(struct bio *bio)
 {
-       struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+       struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+       struct thin_c *tc = h->tc;
        struct pool *pool = tc->pool;
        unsigned long flags;
 
@@ -1102,6 +1174,86 @@ static void no_space(struct cell *cell)
                retry_on_resume(bio);
 }
 
+static void process_discard(struct thin_c *tc, struct bio *bio)
+{
+       int r;
+       struct pool *pool = tc->pool;
+       struct cell *cell, *cell2;
+       struct cell_key key, key2;
+       dm_block_t block = get_bio_block(tc, bio);
+       struct dm_thin_lookup_result lookup_result;
+       struct new_mapping *m;
+
+       build_virtual_key(tc->td, block, &key);
+       if (bio_detain(tc->pool->prison, &key, bio, &cell))
+               return;
+
+       r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
+       switch (r) {
+       case 0:
+               /*
+                * Check nobody is fiddling with this pool block.  This can
+                * happen if someone's in the process of breaking sharing
+                * on this block.
+                */
+               build_data_key(tc->td, lookup_result.block, &key2);
+               if (bio_detain(tc->pool->prison, &key2, bio, &cell2)) {
+                       cell_release_singleton(cell, bio);
+                       break;
+               }
+
+               if (io_overlaps_block(pool, bio)) {
+                       /*
+                        * IO may still be going to the destination block.  We must
+                        * quiesce before we can do the removal.
+                        */
+                       m = get_next_mapping(pool);
+                       m->tc = tc;
+                       m->pass_discard = (!lookup_result.shared) & pool->pf.discard_passdown;
+                       m->virt_block = block;
+                       m->data_block = lookup_result.block;
+                       m->cell = cell;
+                       m->cell2 = cell2;
+                       m->err = 0;
+                       m->bio = bio;
+
+                       if (!ds_add_work(&pool->all_io_ds, &m->list)) {
+                               list_add(&m->list, &pool->prepared_discards);
+                               wake_worker(pool);
+                       }
+               } else {
+                       /*
+                        * This path is hit if people are ignoring
+                        * limits->discard_granularity.  It ignores any
+                        * part of the discard that is in a subsequent
+                        * block.
+                        */
+                       sector_t offset = bio->bi_sector - (block << pool->block_shift);
+                       unsigned remaining = (pool->sectors_per_block - offset) << 9;
+                       bio->bi_size = min(bio->bi_size, remaining);
+
+                       cell_release_singleton(cell, bio);
+                       cell_release_singleton(cell2, bio);
+                       remap_and_issue(tc, bio, lookup_result.block);
+               }
+               break;
+
+       case -ENODATA:
+               /*
+                * It isn't provisioned, just forget it.
+                */
+               cell_release_singleton(cell, bio);
+               bio_endio(bio, 0);
+               break;
+
+       default:
+               DMERR("discard: find block unexpectedly returned %d", r);
+               cell_release_singleton(cell, bio);
+               bio_io_error(bio);
+               break;
+       }
+}
+
 static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
                          struct cell_key *key,
                          struct dm_thin_lookup_result *lookup_result,
@@ -1113,8 +1265,8 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
        r = alloc_data_block(tc, &data_block);
        switch (r) {
        case 0:
-               schedule_copy(tc, block, lookup_result->block,
-                             data_block, cell, bio);
+               schedule_internal_copy(tc, block, lookup_result->block,
+                                      data_block, cell, bio);
                break;
 
        case -ENOSPC:
@@ -1147,13 +1299,9 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
        if (bio_data_dir(bio) == WRITE)
                break_sharing(tc, bio, block, &key, lookup_result, cell);
        else {
-               struct endio_hook *h;
-               h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
 
-               h->tc = tc;
-               h->entry = ds_inc(&pool->ds);
-               save_and_set_endio(bio, &h->saved_bi_end_io, shared_read_endio);
-               dm_get_mapinfo(bio)->ptr = h;
+               h->shared_read_entry = ds_inc(&pool->shared_read_ds);
 
                cell_release_singleton(cell, bio);
                remap_and_issue(tc, bio, lookup_result->block);
@@ -1188,7 +1336,10 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
        r = alloc_data_block(tc, &data_block);
        switch (r) {
        case 0:
-               schedule_zero(tc, block, data_block, cell, bio);
+               if (tc->origin_dev)
+                       schedule_external_copy(tc, block, data_block, cell, bio);
+               else
+                       schedule_zero(tc, block, data_block, cell, bio);
                break;
 
        case -ENOSPC:
@@ -1239,16 +1390,27 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
                break;
 
        case -ENODATA:
-               provision_block(tc, bio, block, cell);
+               if (bio_data_dir(bio) == READ && tc->origin_dev) {
+                       cell_release_singleton(cell, bio);
+                       remap_to_origin_and_issue(tc, bio);
+               } else
+                       provision_block(tc, bio, block, cell);
                break;
 
        default:
                DMERR("dm_thin_find_block() failed, error = %d", r);
+               cell_release_singleton(cell, bio);
                bio_io_error(bio);
                break;
        }
 }
 
+static int need_commit_due_to_time(struct pool *pool)
+{
+       return jiffies < pool->last_commit_jiffies ||
+              jiffies > pool->last_commit_jiffies + COMMIT_PERIOD;
+}
+
 static void process_deferred_bios(struct pool *pool)
 {
        unsigned long flags;
@@ -1264,7 +1426,9 @@ static void process_deferred_bios(struct pool *pool)
        spin_unlock_irqrestore(&pool->lock, flags);
 
        while ((bio = bio_list_pop(&bios))) {
-               struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct thin_c *tc = h->tc;
+
                /*
                 * If we've got no free new_mapping structs, and processing
                 * this bio might require one, we pause until there are some
@@ -1277,7 +1441,11 @@ static void process_deferred_bios(struct pool *pool)
 
                        break;
                }
-               process_bio(tc, bio);
+
+               if (bio->bi_rw & REQ_DISCARD)
+                       process_discard(tc, bio);
+               else
+                       process_bio(tc, bio);
        }
 
        /*
@@ -1290,7 +1458,7 @@ static void process_deferred_bios(struct pool *pool)
        bio_list_init(&pool->deferred_flush_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios))
+       if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
                return;
 
        r = dm_pool_commit_metadata(pool->pmd);
@@ -1301,6 +1469,7 @@ static void process_deferred_bios(struct pool *pool)
                        bio_io_error(bio);
                return;
        }
+       pool->last_commit_jiffies = jiffies;
 
        while ((bio = bio_list_pop(&bios)))
                generic_make_request(bio);
@@ -1310,10 +1479,22 @@ static void do_worker(struct work_struct *ws)
 {
        struct pool *pool = container_of(ws, struct pool, worker);
 
-       process_prepared_mappings(pool);
+       process_prepared(pool, &pool->prepared_mappings, process_prepared_mapping);
+       process_prepared(pool, &pool->prepared_discards, process_prepared_discard);
        process_deferred_bios(pool);
 }
 
+/*
+ * We want to commit periodically so that not too much
+ * unwritten data builds up.
+ */
+static void do_waker(struct work_struct *ws)
+{
+       struct pool *pool = container_of(to_delayed_work(ws), struct pool, waker);
+       wake_worker(pool);
+       queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
+}
+
 /*----------------------------------------------------------------*/
 
 /*
@@ -1335,6 +1516,19 @@ static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
        wake_worker(pool);
 }
 
+static struct endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+       struct endio_hook *h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+
+       h->tc = tc;
+       h->shared_read_entry = NULL;
+       h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : ds_inc(&pool->all_io_ds);
+       h->overwrite_mapping = NULL;
+
+       return h;
+}
+
 /*
  * Non-blocking function called from the thin target's map function.
  */
@@ -1347,12 +1541,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
        struct dm_thin_device *td = tc->td;
        struct dm_thin_lookup_result result;
 
-       /*
-        * Save the thin context for easy access from the deferred bio later.
-        */
-       map_context->ptr = tc;
-
-       if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+       map_context->ptr = thin_hook_bio(tc, bio);
+       if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) {
                thin_defer_bio(tc, bio);
                return DM_MAPIO_SUBMITTED;
        }
@@ -1434,7 +1624,7 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
 
        pool->ti = ti;
        pool->low_water_blocks = pt->low_water_blocks;
-       pool->zero_new_blocks = pt->zero_new_blocks;
+       pool->pf = pt->pf;
 
        return 0;
 }
@@ -1448,6 +1638,14 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti)
 /*----------------------------------------------------------------
  * Pool creation
  *--------------------------------------------------------------*/
+/* Initialize pool features. */
+static void pool_features_init(struct pool_features *pf)
+{
+       pf->zero_new_blocks = 1;
+       pf->discard_enabled = 1;
+       pf->discard_passdown = 1;
+}
+
 static void __pool_destroy(struct pool *pool)
 {
        __pool_table_remove(pool);
@@ -1495,7 +1693,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        pool->block_shift = ffs(block_size) - 1;
        pool->offset_mask = block_size - 1;
        pool->low_water_blocks = 0;
-       pool->zero_new_blocks = 1;
+       pool_features_init(&pool->pf);
        pool->prison = prison_create(PRISON_CELLS);
        if (!pool->prison) {
                *error = "Error creating pool's bio prison";
@@ -1523,14 +1721,17 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        }
 
        INIT_WORK(&pool->worker, do_worker);
+       INIT_DELAYED_WORK(&pool->waker, do_waker);
        spin_lock_init(&pool->lock);
        bio_list_init(&pool->deferred_bios);
        bio_list_init(&pool->deferred_flush_bios);
        INIT_LIST_HEAD(&pool->prepared_mappings);
+       INIT_LIST_HEAD(&pool->prepared_discards);
        pool->low_water_triggered = 0;
        pool->no_free_space = 0;
        bio_list_init(&pool->retry_on_resume_list);
-       ds_init(&pool->ds);
+       ds_init(&pool->shared_read_ds);
+       ds_init(&pool->all_io_ds);
 
        pool->next_mapping = NULL;
        pool->mapping_pool =
@@ -1549,6 +1750,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
                goto bad_endio_hook_pool;
        }
        pool->ref_count = 1;
+       pool->last_commit_jiffies = jiffies;
        pool->pool_md = pool_md;
        pool->md_dev = metadata_dev;
        __pool_table_insert(pool);
@@ -1588,7 +1790,8 @@ static void __pool_dec(struct pool *pool)
 
 static struct pool *__pool_find(struct mapped_device *pool_md,
                                struct block_device *metadata_dev,
-                               unsigned long block_size, char **error)
+                               unsigned long block_size, char **error,
+                               int *created)
 {
        struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
 
@@ -1604,8 +1807,10 @@ static struct pool *__pool_find(struct mapped_device *pool_md,
                                return ERR_PTR(-EINVAL);
                        __pool_inc(pool);
 
-               } else
+               } else {
                        pool = pool_create(pool_md, metadata_dev, block_size, error);
+                       *created = 1;
+               }
        }
 
        return pool;
@@ -1629,10 +1834,6 @@ static void pool_dtr(struct dm_target *ti)
        mutex_unlock(&dm_thin_pool_table.mutex);
 }
 
-struct pool_features {
-       unsigned zero_new_blocks:1;
-};
-
 static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
                               struct dm_target *ti)
 {
@@ -1641,7 +1842,7 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
        const char *arg_name;
 
        static struct dm_arg _args[] = {
-               {0, 1, "Invalid number of pool feature arguments"},
+               {0, 3, "Invalid number of pool feature arguments"},
        };
 
        /*
@@ -1661,6 +1862,12 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
                if (!strcasecmp(arg_name, "skip_block_zeroing")) {
                        pf->zero_new_blocks = 0;
                        continue;
+               } else if (!strcasecmp(arg_name, "ignore_discard")) {
+                       pf->discard_enabled = 0;
+                       continue;
+               } else if (!strcasecmp(arg_name, "no_discard_passdown")) {
+                       pf->discard_passdown = 0;
+                       continue;
                }
 
                ti->error = "Unrecognised pool feature requested";
@@ -1678,10 +1885,12 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
  *
  * Optional feature arguments are:
  *          skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
+ *          ignore_discard: disable discard
+ *          no_discard_passdown: don't pass discards down to the data device
  */
 static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
-       int r;
+       int r, pool_created = 0;
        struct pool_c *pt;
        struct pool *pool;
        struct pool_features pf;
@@ -1691,6 +1900,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        dm_block_t low_water_blocks;
        struct dm_dev *metadata_dev;
        sector_t metadata_dev_size;
+       char b[BDEVNAME_SIZE];
 
        /*
         * FIXME Remove validation from scope of lock.
@@ -1712,11 +1922,9 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
-       if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) {
-               ti->error = "Metadata device is too large";
-               r = -EINVAL;
-               goto out_metadata;
-       }
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
+               DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
+                      bdevname(metadata_dev->bdev, b), THIN_METADATA_MAX_SECTORS);
 
        r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
        if (r) {
@@ -1742,8 +1950,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        /*
         * Set default pool features.
         */
-       memset(&pf, 0, sizeof(pf));
-       pf.zero_new_blocks = 1;
+       pool_features_init(&pf);
 
        dm_consume_args(&as, 4);
        r = parse_pool_features(&as, &pf, ti);
@@ -1757,20 +1964,58 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
-                          block_size, &ti->error);
+                          block_size, &ti->error, &pool_created);
        if (IS_ERR(pool)) {
                r = PTR_ERR(pool);
                goto out_free_pt;
        }
 
+       /*
+        * 'pool_created' reflects whether this is the first table load.
+        * Top level discard support is not allowed to be changed after
+        * initial load.  This would require a pool reload to trigger thin
+        * device changes.
+        */
+       if (!pool_created && pf.discard_enabled != pool->pf.discard_enabled) {
+               ti->error = "Discard support cannot be disabled once enabled";
+               r = -EINVAL;
+               goto out_flags_changed;
+       }
+
+       /*
+        * If discard_passdown was enabled verify that the data device
+        * supports discards.  Disable discard_passdown if not; otherwise
+        * -EOPNOTSUPP will be returned.
+        */
+       if (pf.discard_passdown) {
+               struct request_queue *q = bdev_get_queue(data_dev->bdev);
+               if (!q || !blk_queue_discard(q)) {
+                       DMWARN("Discard unsupported by data device: Disabling discard passdown.");
+                       pf.discard_passdown = 0;
+               }
+       }
+
        pt->pool = pool;
        pt->ti = ti;
        pt->metadata_dev = metadata_dev;
        pt->data_dev = data_dev;
        pt->low_water_blocks = low_water_blocks;
-       pt->zero_new_blocks = pf.zero_new_blocks;
+       pt->pf = pf;
        ti->num_flush_requests = 1;
-       ti->num_discard_requests = 0;
+       /*
+        * Only need to enable discards if the pool should pass
+        * them down to the data device.  The thin device's discard
+        * processing will cause mappings to be removed from the btree.
+        */
+       if (pf.discard_enabled && pf.discard_passdown) {
+               ti->num_discard_requests = 1;
+               /*
+                * Setting 'discards_supported' circumvents the normal
+                * stacking of discard limits (this keeps the pool and
+                * thin devices' discard limits consistent).
+                */
+               ti->discards_supported = 1;
+       }
        ti->private = pt;
 
        pt->callbacks.congested_fn = pool_is_congested;
@@ -1780,6 +2025,8 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        return 0;
 
+out_flags_changed:
+       __pool_dec(pool);
 out_free_pt:
        kfree(pt);
 out:
@@ -1878,7 +2125,7 @@ static void pool_resume(struct dm_target *ti)
        __requeue_bios(pool);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       wake_worker(pool);
+       do_waker(&pool->waker.work);
 }
 
 static void pool_postsuspend(struct dm_target *ti)
@@ -1887,6 +2134,7 @@ static void pool_postsuspend(struct dm_target *ti)
        struct pool_c *pt = ti->private;
        struct pool *pool = pt->pool;
 
+       cancel_delayed_work(&pool->waker);
        flush_workqueue(pool->wq);
 
        r = dm_pool_commit_metadata(pool->pmd);
@@ -2067,7 +2315,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
 static int pool_status(struct dm_target *ti, status_type_t type,
                       char *result, unsigned maxlen)
 {
-       int r;
+       int r, count;
        unsigned sz = 0;
        uint64_t transaction_id;
        dm_block_t nr_free_blocks_data;
@@ -2130,10 +2378,19 @@ static int pool_status(struct dm_target *ti, status_type_t type,
                       (unsigned long)pool->sectors_per_block,
                       (unsigned long long)pt->low_water_blocks);
 
-               DMEMIT("%u ", !pool->zero_new_blocks);
+               count = !pool->pf.zero_new_blocks + !pool->pf.discard_enabled +
+                       !pool->pf.discard_passdown;
+               DMEMIT("%u ", count);
 
-               if (!pool->zero_new_blocks)
+               if (!pool->pf.zero_new_blocks)
                        DMEMIT("skip_block_zeroing ");
+
+               if (!pool->pf.discard_enabled)
+                       DMEMIT("ignore_discard ");
+
+               if (!pool->pf.discard_passdown)
+                       DMEMIT("no_discard_passdown ");
+
                break;
        }
 
@@ -2162,6 +2419,21 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
        return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
 
+static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
+{
+       /*
+        * FIXME: these limits may be incompatible with the pool's data device
+        */
+       limits->max_discard_sectors = pool->sectors_per_block;
+
+       /*
+        * This is just a hint, and not enforced.  We have to cope with
+        * bios that overlap 2 blocks.
+        */
+       limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
+       limits->discard_zeroes_data = pool->pf.zero_new_blocks;
+}
+
 static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct pool_c *pt = ti->private;
@@ -2169,13 +2441,15 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
        blk_limits_io_min(limits, 0);
        blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+       if (pool->pf.discard_enabled)
+               set_discard_limits(pool, limits);
 }
 
 static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2202,6 +2476,8 @@ static void thin_dtr(struct dm_target *ti)
        __pool_dec(tc->pool);
        dm_pool_close_thin_device(tc->td);
        dm_put_device(ti, tc->pool_dev);
+       if (tc->origin_dev)
+               dm_put_device(ti, tc->origin_dev);
        kfree(tc);
 
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -2210,21 +2486,25 @@ static void thin_dtr(struct dm_target *ti)
 /*
  * Thin target parameters:
  *
- * <pool_dev> <dev_id>
+ * <pool_dev> <dev_id> [origin_dev]
  *
  * pool_dev: the path to the pool (eg, /dev/mapper/my_pool)
  * dev_id: the internal device identifier
+ * origin_dev: a device external to the pool that should act as the origin
+ *
+ * If the pool device has discards disabled, they get disabled for the thin
+ * device as well.
  */
 static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
        int r;
        struct thin_c *tc;
-       struct dm_dev *pool_dev;
+       struct dm_dev *pool_dev, *origin_dev;
        struct mapped_device *pool_md;
 
        mutex_lock(&dm_thin_pool_table.mutex);
 
-       if (argc != 2) {
+       if (argc != 2 && argc != 3) {
                ti->error = "Invalid argument count";
                r = -EINVAL;
                goto out_unlock;
@@ -2237,6 +2517,15 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto out_unlock;
        }
 
+       if (argc == 3) {
+               r = dm_get_device(ti, argv[2], FMODE_READ, &origin_dev);
+               if (r) {
+                       ti->error = "Error opening origin device";
+                       goto bad_origin_dev;
+               }
+               tc->origin_dev = origin_dev;
+       }
+
        r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev);
        if (r) {
                ti->error = "Error opening pool device";
@@ -2273,8 +2562,12 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        ti->split_io = tc->pool->sectors_per_block;
        ti->num_flush_requests = 1;
-       ti->num_discard_requests = 0;
-       ti->discards_supported = 0;
+
+       /* In case the pool supports discards, pass them on. */
+       if (tc->pool->pf.discard_enabled) {
+               ti->discards_supported = 1;
+               ti->num_discard_requests = 1;
+       }
 
        dm_put(pool_md);
 
@@ -2289,6 +2582,9 @@ bad_pool_lookup:
 bad_common:
        dm_put_device(ti, tc->pool_dev);
 bad_pool_dev:
+       if (tc->origin_dev)
+               dm_put_device(ti, tc->origin_dev);
+bad_origin_dev:
        kfree(tc);
 out_unlock:
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -2299,11 +2595,46 @@ out_unlock:
 static int thin_map(struct dm_target *ti, struct bio *bio,
                    union map_info *map_context)
 {
-       bio->bi_sector -= ti->begin;
+       bio->bi_sector = dm_target_offset(ti, bio->bi_sector);
 
        return thin_bio_map(ti, bio, map_context);
 }
 
+static int thin_endio(struct dm_target *ti,
+                     struct bio *bio, int err,
+                     union map_info *map_context)
+{
+       unsigned long flags;
+       struct endio_hook *h = map_context->ptr;
+       struct list_head work;
+       struct new_mapping *m, *tmp;
+       struct pool *pool = h->tc->pool;
+
+       if (h->shared_read_entry) {
+               INIT_LIST_HEAD(&work);
+               ds_dec(h->shared_read_entry, &work);
+
+               spin_lock_irqsave(&pool->lock, flags);
+               list_for_each_entry_safe(m, tmp, &work, list) {
+                       list_del(&m->list);
+                       m->quiesced = 1;
+                       __maybe_add_mapping(m);
+               }
+               spin_unlock_irqrestore(&pool->lock, flags);
+       }
+
+       if (h->all_io_entry) {
+               INIT_LIST_HEAD(&work);
+               ds_dec(h->all_io_entry, &work);
+               list_for_each_entry_safe(m, tmp, &work, list)
+                       list_add(&m->list, &pool->prepared_discards);
+       }
+
+       mempool_free(h, pool->endio_hook_pool);
+
+       return 0;
+}
+
 static void thin_postsuspend(struct dm_target *ti)
 {
        if (dm_noflush_suspending(ti))
@@ -2347,6 +2678,8 @@ static int thin_status(struct dm_target *ti, status_type_t type,
                        DMEMIT("%s %lu",
                               format_dev_t(buf, tc->pool_dev->bdev->bd_dev),
                               (unsigned long) tc->dev_id);
+                       if (tc->origin_dev)
+                               DMEMIT(" %s", format_dev_t(buf, tc->origin_dev->bdev->bd_dev));
                        break;
                }
        }
@@ -2377,18 +2710,21 @@ static int thin_iterate_devices(struct dm_target *ti,
 static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct thin_c *tc = ti->private;
+       struct pool *pool = tc->pool;
 
        blk_limits_io_min(limits, 0);
-       blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
+       blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+       set_discard_limits(pool, limits);
 }
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
        .map = thin_map,
+       .end_io = thin_endio,
        .postsuspend = thin_postsuspend,
        .status = thin_status,
        .iterate_devices = thin_iterate_devices,
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
new file mode 100644 (file)
index 0000000..fa365d3
--- /dev/null
@@ -0,0 +1,913 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * Based on Chromium dm-verity driver (C) 2011 The Chromium OS Authors
+ *
+ * This file is released under the GPLv2.
+ *
+ * In the file "/sys/module/dm_verity/parameters/prefetch_cluster" you can set
+ * default prefetch value. Data are read in "prefetch_cluster" chunks from the
+ * hash device. Setting this greatly improves performance when data and hash
+ * are on the same disk on different partitions on devices with poor random
+ * access behavior.
+ */
+
+#include "dm-bufio.h"
+
+#include <linux/module.h>
+#include <linux/device-mapper.h>
+#include <crypto/hash.h>
+
+#define DM_MSG_PREFIX                  "verity"
+
+#define DM_VERITY_IO_VEC_INLINE                16
+#define DM_VERITY_MEMPOOL_SIZE         4
+#define DM_VERITY_DEFAULT_PREFETCH_SIZE        262144
+
+#define DM_VERITY_MAX_LEVELS           63
+
+static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
+
+module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, S_IRUGO | S_IWUSR);
+
+struct dm_verity {
+       struct dm_dev *data_dev;
+       struct dm_dev *hash_dev;
+       struct dm_target *ti;
+       struct dm_bufio_client *bufio;
+       char *alg_name;
+       struct crypto_shash *tfm;
+       u8 *root_digest;        /* digest of the root block */
+       u8 *salt;               /* salt: its size is salt_size */
+       unsigned salt_size;
+       sector_t data_start;    /* data offset in 512-byte sectors */
+       sector_t hash_start;    /* hash start in blocks */
+       sector_t data_blocks;   /* the number of data blocks */
+       sector_t hash_blocks;   /* the number of hash blocks */
+       unsigned char data_dev_block_bits;      /* log2(data blocksize) */
+       unsigned char hash_dev_block_bits;      /* log2(hash blocksize) */
+       unsigned char hash_per_block_bits;      /* log2(hashes in hash block) */
+       unsigned char levels;   /* the number of tree levels */
+       unsigned char version;
+       unsigned digest_size;   /* digest size for the current hash algorithm */
+       unsigned shash_descsize;/* the size of temporary space for crypto */
+       int hash_failed;        /* set to 1 if hash of any block failed */
+
+       mempool_t *io_mempool;  /* mempool of struct dm_verity_io */
+       mempool_t *vec_mempool; /* mempool of bio vector */
+
+       struct workqueue_struct *verify_wq;
+
+       /* starting blocks for each tree level. 0 is the lowest level. */
+       sector_t hash_level_block[DM_VERITY_MAX_LEVELS];
+};
+
+struct dm_verity_io {
+       struct dm_verity *v;
+       struct bio *bio;
+
+       /* original values of bio->bi_end_io and bio->bi_private */
+       bio_end_io_t *orig_bi_end_io;
+       void *orig_bi_private;
+
+       sector_t block;
+       unsigned n_blocks;
+
+       /* saved bio vector */
+       struct bio_vec *io_vec;
+       unsigned io_vec_size;
+
+       struct work_struct work;
+
+       /* A space for short vectors; longer vectors are allocated separately. */
+       struct bio_vec io_vec_inline[DM_VERITY_IO_VEC_INLINE];
+
+       /*
+        * Three variably-size fields follow this struct:
+        *
+        * u8 hash_desc[v->shash_descsize];
+        * u8 real_digest[v->digest_size];
+        * u8 want_digest[v->digest_size];
+        *
+        * To access them use: io_hash_desc(), io_real_digest() and io_want_digest().
+        */
+};
+
+static struct shash_desc *io_hash_desc(struct dm_verity *v, struct dm_verity_io *io)
+{
+       return (struct shash_desc *)(io + 1);
+}
+
+static u8 *io_real_digest(struct dm_verity *v, struct dm_verity_io *io)
+{
+       return (u8 *)(io + 1) + v->shash_descsize;
+}
+
+static u8 *io_want_digest(struct dm_verity *v, struct dm_verity_io *io)
+{
+       return (u8 *)(io + 1) + v->shash_descsize + v->digest_size;
+}
+
+/*
+ * Auxiliary structure appended to each dm-bufio buffer. If the value
+ * hash_verified is nonzero, hash of the block has been verified.
+ *
+ * The variable hash_verified is set to 0 when allocating the buffer, then
+ * it can be changed to 1 and it is never reset to 0 again.
+ *
+ * There is no lock around this value, a race condition can at worst cause
+ * that multiple processes verify the hash of the same buffer simultaneously
+ * and write 1 to hash_verified simultaneously.
+ * This condition is harmless, so we don't need locking.
+ */
+struct buffer_aux {
+       int hash_verified;
+};
+
+/*
+ * Initialize struct buffer_aux for a freshly created buffer.
+ */
+static void dm_bufio_alloc_callback(struct dm_buffer *buf)
+{
+       struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+
+       aux->hash_verified = 0;
+}
+
+/*
+ * Translate input sector number to the sector number on the target device.
+ */
+static sector_t verity_map_sector(struct dm_verity *v, sector_t bi_sector)
+{
+       return v->data_start + dm_target_offset(v->ti, bi_sector);
+}
+
+/*
+ * Return hash position of a specified block at a specified tree level
+ * (0 is the lowest level).
+ * The lowest "hash_per_block_bits"-bits of the result denote hash position
+ * inside a hash block. The remaining bits denote location of the hash block.
+ */
+static sector_t verity_position_at_level(struct dm_verity *v, sector_t block,
+                                        int level)
+{
+       return block >> (level * v->hash_per_block_bits);
+}
+
+static void verity_hash_at_level(struct dm_verity *v, sector_t block, int level,
+                                sector_t *hash_block, unsigned *offset)
+{
+       sector_t position = verity_position_at_level(v, block, level);
+       unsigned idx;
+
+       *hash_block = v->hash_level_block[level] + (position >> v->hash_per_block_bits);
+
+       if (!offset)
+               return;
+
+       idx = position & ((1 << v->hash_per_block_bits) - 1);
+       if (!v->version)
+               *offset = idx * v->digest_size;
+       else
+               *offset = idx << (v->hash_dev_block_bits - v->hash_per_block_bits);
+}
+
+/*
+ * Verify hash of a metadata block pertaining to the specified data block
+ * ("block" argument) at a specified level ("level" argument).
+ *
+ * On successful return, io_want_digest(v, io) contains the hash value for
+ * a lower tree level or for the data block (if we're at the lowest leve).
+ *
+ * If "skip_unverified" is true, unverified buffer is skipped and 1 is returned.
+ * If "skip_unverified" is false, unverified buffer is hashed and verified
+ * against current value of io_want_digest(v, io).
+ */
+static int verity_verify_level(struct dm_verity_io *io, sector_t block,
+                              int level, bool skip_unverified)
+{
+       struct dm_verity *v = io->v;
+       struct dm_buffer *buf;
+       struct buffer_aux *aux;
+       u8 *data;
+       int r;
+       sector_t hash_block;
+       unsigned offset;
+
+       verity_hash_at_level(v, block, level, &hash_block, &offset);
+
+       data = dm_bufio_read(v->bufio, hash_block, &buf);
+       if (unlikely(IS_ERR(data)))
+               return PTR_ERR(data);
+
+       aux = dm_bufio_get_aux_data(buf);
+
+       if (!aux->hash_verified) {
+               struct shash_desc *desc;
+               u8 *result;
+
+               if (skip_unverified) {
+                       r = 1;
+                       goto release_ret_r;
+               }
+
+               desc = io_hash_desc(v, io);
+               desc->tfm = v->tfm;
+               desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+               r = crypto_shash_init(desc);
+               if (r < 0) {
+                       DMERR("crypto_shash_init failed: %d", r);
+                       goto release_ret_r;
+               }
+
+               if (likely(v->version >= 1)) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               goto release_ret_r;
+                       }
+               }
+
+               r = crypto_shash_update(desc, data, 1 << v->hash_dev_block_bits);
+               if (r < 0) {
+                       DMERR("crypto_shash_update failed: %d", r);
+                       goto release_ret_r;
+               }
+
+               if (!v->version) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               goto release_ret_r;
+                       }
+               }
+
+               result = io_real_digest(v, io);
+               r = crypto_shash_final(desc, result);
+               if (r < 0) {
+                       DMERR("crypto_shash_final failed: %d", r);
+                       goto release_ret_r;
+               }
+               if (unlikely(memcmp(result, io_want_digest(v, io), v->digest_size))) {
+                       DMERR_LIMIT("metadata block %llu is corrupted",
+                               (unsigned long long)hash_block);
+                       v->hash_failed = 1;
+                       r = -EIO;
+                       goto release_ret_r;
+               } else
+                       aux->hash_verified = 1;
+       }
+
+       data += offset;
+
+       memcpy(io_want_digest(v, io), data, v->digest_size);
+
+       dm_bufio_release(buf);
+       return 0;
+
+release_ret_r:
+       dm_bufio_release(buf);
+
+       return r;
+}
+
+/*
+ * Verify one "dm_verity_io" structure.
+ */
+static int verity_verify_io(struct dm_verity_io *io)
+{
+       struct dm_verity *v = io->v;
+       unsigned b;
+       int i;
+       unsigned vector = 0, offset = 0;
+
+       for (b = 0; b < io->n_blocks; b++) {
+               struct shash_desc *desc;
+               u8 *result;
+               int r;
+               unsigned todo;
+
+               if (likely(v->levels)) {
+                       /*
+                        * First, we try to get the requested hash for
+                        * the current block. If the hash block itself is
+                        * verified, zero is returned. If it isn't, this
+                        * function returns 0 and we fall back to whole
+                        * chain verification.
+                        */
+                       int r = verity_verify_level(io, io->block + b, 0, true);
+                       if (likely(!r))
+                               goto test_block_hash;
+                       if (r < 0)
+                               return r;
+               }
+
+               memcpy(io_want_digest(v, io), v->root_digest, v->digest_size);
+
+               for (i = v->levels - 1; i >= 0; i--) {
+                       int r = verity_verify_level(io, io->block + b, i, false);
+                       if (unlikely(r))
+                               return r;
+               }
+
+test_block_hash:
+               desc = io_hash_desc(v, io);
+               desc->tfm = v->tfm;
+               desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+               r = crypto_shash_init(desc);
+               if (r < 0) {
+                       DMERR("crypto_shash_init failed: %d", r);
+                       return r;
+               }
+
+               if (likely(v->version >= 1)) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               return r;
+                       }
+               }
+
+               todo = 1 << v->data_dev_block_bits;
+               do {
+                       struct bio_vec *bv;
+                       u8 *page;
+                       unsigned len;
+
+                       BUG_ON(vector >= io->io_vec_size);
+                       bv = &io->io_vec[vector];
+                       page = kmap_atomic(bv->bv_page);
+                       len = bv->bv_len - offset;
+                       if (likely(len >= todo))
+                               len = todo;
+                       r = crypto_shash_update(desc,
+                                       page + bv->bv_offset + offset, len);
+                       kunmap_atomic(page);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               return r;
+                       }
+                       offset += len;
+                       if (likely(offset == bv->bv_len)) {
+                               offset = 0;
+                               vector++;
+                       }
+                       todo -= len;
+               } while (todo);
+
+               if (!v->version) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               return r;
+                       }
+               }
+
+               result = io_real_digest(v, io);
+               r = crypto_shash_final(desc, result);
+               if (r < 0) {
+                       DMERR("crypto_shash_final failed: %d", r);
+                       return r;
+               }
+               if (unlikely(memcmp(result, io_want_digest(v, io), v->digest_size))) {
+                       DMERR_LIMIT("data block %llu is corrupted",
+                               (unsigned long long)(io->block + b));
+                       v->hash_failed = 1;
+                       return -EIO;
+               }
+       }
+       BUG_ON(vector != io->io_vec_size);
+       BUG_ON(offset);
+
+       return 0;
+}
+
+/*
+ * End one "io" structure with a given error.
+ */
+static void verity_finish_io(struct dm_verity_io *io, int error)
+{
+       struct bio *bio = io->bio;
+       struct dm_verity *v = io->v;
+
+       bio->bi_end_io = io->orig_bi_end_io;
+       bio->bi_private = io->orig_bi_private;
+
+       if (io->io_vec != io->io_vec_inline)
+               mempool_free(io->io_vec, v->vec_mempool);
+
+       mempool_free(io, v->io_mempool);
+
+       bio_endio(bio, error);
+}
+
+static void verity_work(struct work_struct *w)
+{
+       struct dm_verity_io *io = container_of(w, struct dm_verity_io, work);
+
+       verity_finish_io(io, verity_verify_io(io));
+}
+
+static void verity_end_io(struct bio *bio, int error)
+{
+       struct dm_verity_io *io = bio->bi_private;
+
+       if (error) {
+               verity_finish_io(io, error);
+               return;
+       }
+
+       INIT_WORK(&io->work, verity_work);
+       queue_work(io->v->verify_wq, &io->work);
+}
+
+/*
+ * Prefetch buffers for the specified io.
+ * The root buffer is not prefetched, it is assumed that it will be cached
+ * all the time.
+ */
+static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io)
+{
+       int i;
+
+       for (i = v->levels - 2; i >= 0; i--) {
+               sector_t hash_block_start;
+               sector_t hash_block_end;
+               verity_hash_at_level(v, io->block, i, &hash_block_start, NULL);
+               verity_hash_at_level(v, io->block + io->n_blocks - 1, i, &hash_block_end, NULL);
+               if (!i) {
+                       unsigned cluster = *(volatile unsigned *)&dm_verity_prefetch_cluster;
+
+                       cluster >>= v->data_dev_block_bits;
+                       if (unlikely(!cluster))
+                               goto no_prefetch_cluster;
+
+                       if (unlikely(cluster & (cluster - 1)))
+                               cluster = 1 << (fls(cluster) - 1);
+
+                       hash_block_start &= ~(sector_t)(cluster - 1);
+                       hash_block_end |= cluster - 1;
+                       if (unlikely(hash_block_end >= v->hash_blocks))
+                               hash_block_end = v->hash_blocks - 1;
+               }
+no_prefetch_cluster:
+               dm_bufio_prefetch(v->bufio, hash_block_start,
+                                 hash_block_end - hash_block_start + 1);
+       }
+}
+
+/*
+ * Bio map function. It allocates dm_verity_io structure and bio vector and
+ * fills them. Then it issues prefetches and the I/O.
+ */
+static int verity_map(struct dm_target *ti, struct bio *bio,
+                     union map_info *map_context)
+{
+       struct dm_verity *v = ti->private;
+       struct dm_verity_io *io;
+
+       bio->bi_bdev = v->data_dev->bdev;
+       bio->bi_sector = verity_map_sector(v, bio->bi_sector);
+
+       if (((unsigned)bio->bi_sector | bio_sectors(bio)) &
+           ((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) {
+               DMERR_LIMIT("unaligned io");
+               return -EIO;
+       }
+
+       if ((bio->bi_sector + bio_sectors(bio)) >>
+           (v->data_dev_block_bits - SECTOR_SHIFT) > v->data_blocks) {
+               DMERR_LIMIT("io out of range");
+               return -EIO;
+       }
+
+       if (bio_data_dir(bio) == WRITE)
+               return -EIO;
+
+       io = mempool_alloc(v->io_mempool, GFP_NOIO);
+       io->v = v;
+       io->bio = bio;
+       io->orig_bi_end_io = bio->bi_end_io;
+       io->orig_bi_private = bio->bi_private;
+       io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
+       io->n_blocks = bio->bi_size >> v->data_dev_block_bits;
+
+       bio->bi_end_io = verity_end_io;
+       bio->bi_private = io;
+       io->io_vec_size = bio->bi_vcnt - bio->bi_idx;
+       if (io->io_vec_size < DM_VERITY_IO_VEC_INLINE)
+               io->io_vec = io->io_vec_inline;
+       else
+               io->io_vec = mempool_alloc(v->vec_mempool, GFP_NOIO);
+       memcpy(io->io_vec, bio_iovec(bio),
+              io->io_vec_size * sizeof(struct bio_vec));
+
+       verity_prefetch_io(v, io);
+
+       generic_make_request(bio);
+
+       return DM_MAPIO_SUBMITTED;
+}
+
+/*
+ * Status: V (valid) or C (corruption found)
+ */
+static int verity_status(struct dm_target *ti, status_type_t type,
+                        char *result, unsigned maxlen)
+{
+       struct dm_verity *v = ti->private;
+       unsigned sz = 0;
+       unsigned x;
+
+       switch (type) {
+       case STATUSTYPE_INFO:
+               DMEMIT("%c", v->hash_failed ? 'C' : 'V');
+               break;
+       case STATUSTYPE_TABLE:
+               DMEMIT("%u %s %s %u %u %llu %llu %s ",
+                       v->version,
+                       v->data_dev->name,
+                       v->hash_dev->name,
+                       1 << v->data_dev_block_bits,
+                       1 << v->hash_dev_block_bits,
+                       (unsigned long long)v->data_blocks,
+                       (unsigned long long)v->hash_start,
+                       v->alg_name
+                       );
+               for (x = 0; x < v->digest_size; x++)
+                       DMEMIT("%02x", v->root_digest[x]);
+               DMEMIT(" ");
+               if (!v->salt_size)
+                       DMEMIT("-");
+               else
+                       for (x = 0; x < v->salt_size; x++)
+                               DMEMIT("%02x", v->salt[x]);
+               break;
+       }
+
+       return 0;
+}
+
+static int verity_ioctl(struct dm_target *ti, unsigned cmd,
+                       unsigned long arg)
+{
+       struct dm_verity *v = ti->private;
+       int r = 0;
+
+       if (v->data_start ||
+           ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
+               r = scsi_verify_blk_ioctl(NULL, cmd);
+
+       return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
+                                    cmd, arg);
+}
+
+static int verity_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+                       struct bio_vec *biovec, int max_size)
+{
+       struct dm_verity *v = ti->private;
+       struct request_queue *q = bdev_get_queue(v->data_dev->bdev);
+
+       if (!q->merge_bvec_fn)
+               return max_size;
+
+       bvm->bi_bdev = v->data_dev->bdev;
+       bvm->bi_sector = verity_map_sector(v, bvm->bi_sector);
+
+       return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static int verity_iterate_devices(struct dm_target *ti,
+                                 iterate_devices_callout_fn fn, void *data)
+{
+       struct dm_verity *v = ti->private;
+
+       return fn(ti, v->data_dev, v->data_start, ti->len, data);
+}
+
+static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+       struct dm_verity *v = ti->private;
+
+       if (limits->logical_block_size < 1 << v->data_dev_block_bits)
+               limits->logical_block_size = 1 << v->data_dev_block_bits;
+
+       if (limits->physical_block_size < 1 << v->data_dev_block_bits)
+               limits->physical_block_size = 1 << v->data_dev_block_bits;
+
+       blk_limits_io_min(limits, limits->logical_block_size);
+}
+
+static void verity_dtr(struct dm_target *ti)
+{
+       struct dm_verity *v = ti->private;
+
+       if (v->verify_wq)
+               destroy_workqueue(v->verify_wq);
+
+       if (v->vec_mempool)
+               mempool_destroy(v->vec_mempool);
+
+       if (v->io_mempool)
+               mempool_destroy(v->io_mempool);
+
+       if (v->bufio)
+               dm_bufio_client_destroy(v->bufio);
+
+       kfree(v->salt);
+       kfree(v->root_digest);
+
+       if (v->tfm)
+               crypto_free_shash(v->tfm);
+
+       kfree(v->alg_name);
+
+       if (v->hash_dev)
+               dm_put_device(ti, v->hash_dev);
+
+       if (v->data_dev)
+               dm_put_device(ti, v->data_dev);
+
+       kfree(v);
+}
+
+/*
+ * Target parameters:
+ *     <version>       The current format is version 1.
+ *                     Vsn 0 is compatible with original Chromium OS releases.
+ *     <data device>
+ *     <hash device>
+ *     <data block size>
+ *     <hash block size>
+ *     <the number of data blocks>
+ *     <hash start block>
+ *     <algorithm>
+ *     <digest>
+ *     <salt>          Hex string or "-" if no salt.
+ */
+static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+       struct dm_verity *v;
+       unsigned num;
+       unsigned long long num_ll;
+       int r;
+       int i;
+       sector_t hash_position;
+       char dummy;
+
+       v = kzalloc(sizeof(struct dm_verity), GFP_KERNEL);
+       if (!v) {
+               ti->error = "Cannot allocate verity structure";
+               return -ENOMEM;
+       }
+       ti->private = v;
+       v->ti = ti;
+
+       if ((dm_table_get_mode(ti->table) & ~FMODE_READ)) {
+               ti->error = "Device must be readonly";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (argc != 10) {
+               ti->error = "Invalid argument count: exactly 10 arguments required";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (sscanf(argv[0], "%d%c", &num, &dummy) != 1 ||
+           num < 0 || num > 1) {
+               ti->error = "Invalid version";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->version = num;
+
+       r = dm_get_device(ti, argv[1], FMODE_READ, &v->data_dev);
+       if (r) {
+               ti->error = "Data device lookup failed";
+               goto bad;
+       }
+
+       r = dm_get_device(ti, argv[2], FMODE_READ, &v->hash_dev);
+       if (r) {
+               ti->error = "Data device lookup failed";
+               goto bad;
+       }
+
+       if (sscanf(argv[3], "%u%c", &num, &dummy) != 1 ||
+           !num || (num & (num - 1)) ||
+           num < bdev_logical_block_size(v->data_dev->bdev) ||
+           num > PAGE_SIZE) {
+               ti->error = "Invalid data device block size";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->data_dev_block_bits = ffs(num) - 1;
+
+       if (sscanf(argv[4], "%u%c", &num, &dummy) != 1 ||
+           !num || (num & (num - 1)) ||
+           num < bdev_logical_block_size(v->hash_dev->bdev) ||
+           num > INT_MAX) {
+               ti->error = "Invalid hash device block size";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->hash_dev_block_bits = ffs(num) - 1;
+
+       if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 ||
+           num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) !=
+           (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) {
+               ti->error = "Invalid data blocks";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->data_blocks = num_ll;
+
+       if (ti->len > (v->data_blocks << (v->data_dev_block_bits - SECTOR_SHIFT))) {
+               ti->error = "Data device is too small";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 ||
+           num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) !=
+           (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) {
+               ti->error = "Invalid hash start";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->hash_start = num_ll;
+
+       v->alg_name = kstrdup(argv[7], GFP_KERNEL);
+       if (!v->alg_name) {
+               ti->error = "Cannot allocate algorithm name";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       v->tfm = crypto_alloc_shash(v->alg_name, 0, 0);
+       if (IS_ERR(v->tfm)) {
+               ti->error = "Cannot initialize hash function";
+               r = PTR_ERR(v->tfm);
+               v->tfm = NULL;
+               goto bad;
+       }
+       v->digest_size = crypto_shash_digestsize(v->tfm);
+       if ((1 << v->hash_dev_block_bits) < v->digest_size * 2) {
+               ti->error = "Digest size too big";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->shash_descsize =
+               sizeof(struct shash_desc) + crypto_shash_descsize(v->tfm);
+
+       v->root_digest = kmalloc(v->digest_size, GFP_KERNEL);
+       if (!v->root_digest) {
+               ti->error = "Cannot allocate root digest";
+               r = -ENOMEM;
+               goto bad;
+       }
+       if (strlen(argv[8]) != v->digest_size * 2 ||
+           hex2bin(v->root_digest, argv[8], v->digest_size)) {
+               ti->error = "Invalid root digest";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (strcmp(argv[9], "-")) {
+               v->salt_size = strlen(argv[9]) / 2;
+               v->salt = kmalloc(v->salt_size, GFP_KERNEL);
+               if (!v->salt) {
+                       ti->error = "Cannot allocate salt";
+                       r = -ENOMEM;
+                       goto bad;
+               }
+               if (strlen(argv[9]) != v->salt_size * 2 ||
+                   hex2bin(v->salt, argv[9], v->salt_size)) {
+                       ti->error = "Invalid salt";
+                       r = -EINVAL;
+                       goto bad;
+               }
+       }
+
+       v->hash_per_block_bits =
+               fls((1 << v->hash_dev_block_bits) / v->digest_size) - 1;
+
+       v->levels = 0;
+       if (v->data_blocks)
+               while (v->hash_per_block_bits * v->levels < 64 &&
+                      (unsigned long long)(v->data_blocks - 1) >>
+                      (v->hash_per_block_bits * v->levels))
+                       v->levels++;
+
+       if (v->levels > DM_VERITY_MAX_LEVELS) {
+               ti->error = "Too many tree levels";
+               r = -E2BIG;
+               goto bad;
+       }
+
+       hash_position = v->hash_start;
+       for (i = v->levels - 1; i >= 0; i--) {
+               sector_t s;
+               v->hash_level_block[i] = hash_position;
+               s = verity_position_at_level(v, v->data_blocks, i);
+               s = (s >> v->hash_per_block_bits) +
+                   !!(s & ((1 << v->hash_per_block_bits) - 1));
+               if (hash_position + s < hash_position) {
+                       ti->error = "Hash device offset overflow";
+                       r = -E2BIG;
+                       goto bad;
+               }
+               hash_position += s;
+       }
+       v->hash_blocks = hash_position;
+
+       v->bufio = dm_bufio_client_create(v->hash_dev->bdev,
+               1 << v->hash_dev_block_bits, 1, sizeof(struct buffer_aux),
+               dm_bufio_alloc_callback, NULL);
+       if (IS_ERR(v->bufio)) {
+               ti->error = "Cannot initialize dm-bufio";
+               r = PTR_ERR(v->bufio);
+               v->bufio = NULL;
+               goto bad;
+       }
+
+       if (dm_bufio_get_device_size(v->bufio) < v->hash_blocks) {
+               ti->error = "Hash device is too small";
+               r = -E2BIG;
+               goto bad;
+       }
+
+       v->io_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE,
+         sizeof(struct dm_verity_io) + v->shash_descsize + v->digest_size * 2);
+       if (!v->io_mempool) {
+               ti->error = "Cannot allocate io mempool";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       v->vec_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE,
+                                       BIO_MAX_PAGES * sizeof(struct bio_vec));
+       if (!v->vec_mempool) {
+               ti->error = "Cannot allocate vector mempool";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       /* WQ_UNBOUND greatly improves performance when running on ramdisk */
+       v->verify_wq = alloc_workqueue("kverityd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus());
+       if (!v->verify_wq) {
+               ti->error = "Cannot allocate workqueue";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       return 0;
+
+bad:
+       verity_dtr(ti);
+
+       return r;
+}
+
+static struct target_type verity_target = {
+       .name           = "verity",
+       .version        = {1, 0, 0},
+       .module         = THIS_MODULE,
+       .ctr            = verity_ctr,
+       .dtr            = verity_dtr,
+       .map            = verity_map,
+       .status         = verity_status,
+       .ioctl          = verity_ioctl,
+       .merge          = verity_merge,
+       .iterate_devices = verity_iterate_devices,
+       .io_hints       = verity_io_hints,
+};
+
+static int __init dm_verity_init(void)
+{
+       int r;
+
+       r = dm_register_target(&verity_target);
+       if (r < 0)
+               DMERR("register failed %d", r);
+
+       return r;
+}
+
+static void __exit dm_verity_exit(void)
+{
+       dm_unregister_target(&verity_target);
+}
+
+module_init(dm_verity_init);
+module_exit(dm_verity_exit);
+
+MODULE_AUTHOR("Mikulas Patocka <mpatocka@redhat.com>");
+MODULE_AUTHOR("Mandeep Baines <msb@chromium.org>");
+MODULE_AUTHOR("Will Drewry <wad@chromium.org>");
+MODULE_DESCRIPTION(DM_NAME " target for transparent disk integrity checking");
+MODULE_LICENSE("GPL");
index b89c548ec3f88612eb4a6fec4d6230ad413ed9c1..e24143cc2040b7f3f8f90a63c3b1b2cfe2b21c24 100644 (file)
@@ -1016,6 +1016,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
                /*
                 * Store bio_set for cleanup.
                 */
+               clone->bi_end_io = NULL;
                clone->bi_private = md->bs;
                bio_put(clone);
                free_tio(md, tio);
index d279c768f8f10f8cf22baef4a6978483c82bb56b..5709bfeab1e8fb29af17ba7a66dc78a9432d86a2 100644 (file)
@@ -108,12 +108,9 @@ static inline void *value_base(struct node *n)
        return &n->keys[le32_to_cpu(n->header.max_entries)];
 }
 
-/*
- * FIXME: Now that value size is stored in node we don't need the third parm.
- */
-static inline void *value_ptr(struct node *n, uint32_t index, size_t value_size)
+static inline void *value_ptr(struct node *n, uint32_t index)
 {
-       BUG_ON(value_size != le32_to_cpu(n->header.value_size));
+       uint32_t value_size = le32_to_cpu(n->header.value_size);
        return value_base(n) + (value_size * index);
 }
 
index 023fbc2d389ee086e2edf53168e969a24dba5cad..aa71e2359a0704050b0b61054d4faa21bac10b53 100644 (file)
@@ -61,20 +61,20 @@ static void node_shift(struct node *n, int shift)
        if (shift < 0) {
                shift = -shift;
                BUG_ON(shift > nr_entries);
-               BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size));
+               BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift));
                memmove(key_ptr(n, 0),
                        key_ptr(n, shift),
                        (nr_entries - shift) * sizeof(__le64));
-               memmove(value_ptr(n, 0, value_size),
-                       value_ptr(n, shift, value_size),
+               memmove(value_ptr(n, 0),
+                       value_ptr(n, shift),
                        (nr_entries - shift) * value_size);
        } else {
                BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries));
                memmove(key_ptr(n, shift),
                        key_ptr(n, 0),
                        nr_entries * sizeof(__le64));
-               memmove(value_ptr(n, shift, value_size),
-                       value_ptr(n, 0, value_size),
+               memmove(value_ptr(n, shift),
+                       value_ptr(n, 0),
                        nr_entries * value_size);
        }
 }
@@ -91,16 +91,16 @@ static void node_copy(struct node *left, struct node *right, int shift)
                memcpy(key_ptr(left, nr_left),
                       key_ptr(right, 0),
                       shift * sizeof(__le64));
-               memcpy(value_ptr(left, nr_left, value_size),
-                      value_ptr(right, 0, value_size),
+               memcpy(value_ptr(left, nr_left),
+                      value_ptr(right, 0),
                       shift * value_size);
        } else {
                BUG_ON(shift > le32_to_cpu(right->header.max_entries));
                memcpy(key_ptr(right, 0),
                       key_ptr(left, nr_left - shift),
                       shift * sizeof(__le64));
-               memcpy(value_ptr(right, 0, value_size),
-                      value_ptr(left, nr_left - shift, value_size),
+               memcpy(value_ptr(right, 0),
+                      value_ptr(left, nr_left - shift),
                       shift * value_size);
        }
 }
@@ -120,26 +120,17 @@ static void delete_at(struct node *n, unsigned index)
                        key_ptr(n, index + 1),
                        nr_to_copy * sizeof(__le64));
 
-               memmove(value_ptr(n, index, value_size),
-                       value_ptr(n, index + 1, value_size),
+               memmove(value_ptr(n, index),
+                       value_ptr(n, index + 1),
                        nr_to_copy * value_size);
        }
 
        n->header.nr_entries = cpu_to_le32(nr_entries - 1);
 }
 
-static unsigned del_threshold(struct node *n)
-{
-       return le32_to_cpu(n->header.max_entries) / 3;
-}
-
 static unsigned merge_threshold(struct node *n)
 {
-       /*
-        * The extra one is because we know we're potentially going to
-        * delete an entry.
-        */
-       return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+       return le32_to_cpu(n->header.max_entries) / 3;
 }
 
 struct child {
@@ -175,7 +166,7 @@ static int init_child(struct dm_btree_info *info, struct node *parent,
        if (inc)
                inc_children(info->tm, result->n, &le64_type);
 
-       *((__le64 *) value_ptr(parent, index, sizeof(__le64))) =
+       *((__le64 *) value_ptr(parent, index)) =
                cpu_to_le64(dm_block_location(result->block));
 
        return 0;
@@ -188,6 +179,15 @@ static int exit_child(struct dm_btree_info *info, struct child *c)
 
 static void shift(struct node *left, struct node *right, int count)
 {
+       uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+       uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+       uint32_t r_max_entries = le32_to_cpu(right->header.max_entries);
+
+       BUG_ON(max_entries != r_max_entries);
+       BUG_ON(nr_left - count > max_entries);
+       BUG_ON(nr_right + count > max_entries);
+
        if (!count)
                return;
 
@@ -199,13 +199,8 @@ static void shift(struct node *left, struct node *right, int count)
                node_shift(right, count);
        }
 
-       left->header.nr_entries =
-               cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
-       BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
-
-       right->header.nr_entries =
-               cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
-       BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+       left->header.nr_entries = cpu_to_le32(nr_left - count);
+       right->header.nr_entries = cpu_to_le32(nr_right + count);
 }
 
 static void __rebalance2(struct dm_btree_info *info, struct node *parent,
@@ -215,8 +210,9 @@ static void __rebalance2(struct dm_btree_info *info, struct node *parent,
        struct node *right = r->n;
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+       unsigned threshold = 2 * merge_threshold(left) + 1;
 
-       if (nr_left + nr_right <= merge_threshold(left)) {
+       if (nr_left + nr_right < threshold) {
                /*
                 * Merge
                 */
@@ -234,9 +230,6 @@ static void __rebalance2(struct dm_btree_info *info, struct node *parent,
                 * Rebalance.
                 */
                unsigned target_left = (nr_left + nr_right) / 2;
-               unsigned shift_ = nr_left - target_left;
-               BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
-               BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
                shift(left, right, nr_left - target_left);
                *key_ptr(parent, r->index) = right->keys[0];
        }
@@ -272,6 +265,84 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
        return exit_child(info, &right);
 }
 
+/*
+ * We dump as many entries from center as possible into left, then the rest
+ * in right, then rebalance2.  This wastes some cpu, but I want something
+ * simple atm.
+ */
+static void delete_center_node(struct dm_btree_info *info, struct node *parent,
+                              struct child *l, struct child *c, struct child *r,
+                              struct node *left, struct node *center, struct node *right,
+                              uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
+{
+       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+       unsigned shift = min(max_entries - nr_left, nr_center);
+
+       BUG_ON(nr_left + shift > max_entries);
+       node_copy(left, center, -shift);
+       left->header.nr_entries = cpu_to_le32(nr_left + shift);
+
+       if (shift != nr_center) {
+               shift = nr_center - shift;
+               BUG_ON((nr_right + shift) > max_entries);
+               node_shift(right, shift);
+               node_copy(center, right, shift);
+               right->header.nr_entries = cpu_to_le32(nr_right + shift);
+       }
+       *key_ptr(parent, r->index) = right->keys[0];
+
+       delete_at(parent, c->index);
+       r->index--;
+
+       dm_tm_dec(info->tm, dm_block_location(c->block));
+       __rebalance2(info, parent, l, r);
+}
+
+/*
+ * Redistributes entries among 3 sibling nodes.
+ */
+static void redistribute3(struct dm_btree_info *info, struct node *parent,
+                         struct child *l, struct child *c, struct child *r,
+                         struct node *left, struct node *center, struct node *right,
+                         uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
+{
+       int s;
+       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+       unsigned target = (nr_left + nr_center + nr_right) / 3;
+       BUG_ON(target > max_entries);
+
+       if (nr_left < nr_right) {
+               s = nr_left - target;
+
+               if (s < 0 && nr_center < -s) {
+                       /* not enough in central node */
+                       shift(left, center, nr_center);
+                       s = nr_center - target;
+                       shift(left, right, s);
+                       nr_right += s;
+               } else
+                       shift(left, center, s);
+
+               shift(center, right, target - nr_right);
+
+       } else {
+               s = target - nr_right;
+               if (s > 0 && nr_center < s) {
+                       /* not enough in central node */
+                       shift(center, right, nr_center);
+                       s = target - nr_center;
+                       shift(left, right, s);
+                       nr_left -= s;
+               } else
+                       shift(center, right, s);
+
+               shift(left, center, nr_left - target);
+       }
+
+       *key_ptr(parent, c->index) = center->keys[0];
+       *key_ptr(parent, r->index) = right->keys[0];
+}
+
 static void __rebalance3(struct dm_btree_info *info, struct node *parent,
                         struct child *l, struct child *c, struct child *r)
 {
@@ -282,62 +353,18 @@ static void __rebalance3(struct dm_btree_info *info, struct node *parent,
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
 
-       unsigned target;
+       unsigned threshold = merge_threshold(left) * 4 + 1;
 
        BUG_ON(left->header.max_entries != center->header.max_entries);
        BUG_ON(center->header.max_entries != right->header.max_entries);
 
-       if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
-               /*
-                * Delete center node:
-                *
-                * We dump as many entries from center as possible into
-                * left, then the rest in right, then rebalance2.  This
-                * wastes some cpu, but I want something simple atm.
-                */
-               unsigned shift = min(max_entries - nr_left, nr_center);
-
-               BUG_ON(nr_left + shift > max_entries);
-               node_copy(left, center, -shift);
-               left->header.nr_entries = cpu_to_le32(nr_left + shift);
-
-               if (shift != nr_center) {
-                       shift = nr_center - shift;
-                       BUG_ON((nr_right + shift) >= max_entries);
-                       node_shift(right, shift);
-                       node_copy(center, right, shift);
-                       right->header.nr_entries = cpu_to_le32(nr_right + shift);
-               }
-               *key_ptr(parent, r->index) = right->keys[0];
-
-               delete_at(parent, c->index);
-               r->index--;
-
-               dm_tm_dec(info->tm, dm_block_location(c->block));
-               __rebalance2(info, parent, l, r);
-
-               return;
-       }
-
-       /*
-        * Rebalance
-        */
-       target = (nr_left + nr_center + nr_right) / 3;
-       BUG_ON(target > max_entries);
-
-       /*
-        * Adjust the left node
-        */
-       shift(left, center, nr_left - target);
-
-       /*
-        * Adjust the right node
-        */
-       shift(center, right, target - nr_right);
-       *key_ptr(parent, c->index) = center->keys[0];
-       *key_ptr(parent, r->index) = right->keys[0];
+       if ((nr_left + nr_center + nr_right) < threshold)
+               delete_center_node(info, parent, l, c, r, left, center, right,
+                                  nr_left, nr_center, nr_right);
+       else
+               redistribute3(info, parent, l, c, r, left, center, right,
+                             nr_left, nr_center, nr_right);
 }
 
 static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
@@ -441,9 +468,6 @@ static int rebalance_children(struct shadow_spine *s,
        if (r)
                return r;
 
-       if (child_entries > del_threshold(n))
-               return 0;
-
        has_left_sibling = i > 0;
        has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
 
@@ -496,7 +520,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
                 */
                if (shadow_has_parent(s)) {
                        __le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
-                       memcpy(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(__le64)),
+                       memcpy(value_ptr(dm_block_data(shadow_parent(s)), i),
                               &location, sizeof(__le64));
                }
 
@@ -553,7 +577,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
 
                if (info->value_type.dec)
                        info->value_type.dec(info->value_type.context,
-                                            value_ptr(n, index, info->value_type.size));
+                                            value_ptr(n, index));
 
                delete_at(n, index);
        }
index bd1e7ffbe26c750a26a4b9341d925a98acf632b3..d12b2cc51f1a37711586fe6d13f6261f0b56c1be 100644 (file)
@@ -74,8 +74,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n,
                        dm_tm_inc(tm, value64(n, i));
        else if (vt->inc)
                for (i = 0; i < nr_entries; i++)
-                       vt->inc(vt->context,
-                               value_ptr(n, i, vt->size));
+                       vt->inc(vt->context, value_ptr(n, i));
 }
 
 static int insert_at(size_t value_size, struct node *node, unsigned index,
@@ -281,7 +280,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
 
                                for (i = 0; i < f->nr_children; i++)
                                        info->value_type.dec(info->value_type.context,
-                                                            value_ptr(f->n, i, info->value_type.size));
+                                                            value_ptr(f->n, i));
                        }
                        f->current_child = f->nr_children;
                }
@@ -320,7 +319,7 @@ static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
        } while (!(flags & LEAF_NODE));
 
        *result_key = le64_to_cpu(ro_node(s)->keys[i]);
-       memcpy(v, value_ptr(ro_node(s), i, value_size), value_size);
+       memcpy(v, value_ptr(ro_node(s), i), value_size);
 
        return 0;
 }
@@ -432,7 +431,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
 
        size = le32_to_cpu(ln->header.flags) & INTERNAL_NODE ?
                sizeof(uint64_t) : s->info->value_type.size;
-       memcpy(value_ptr(rn, 0, size), value_ptr(ln, nr_left, size),
+       memcpy(value_ptr(rn, 0), value_ptr(ln, nr_left),
               size * nr_right);
 
        /*
@@ -443,7 +442,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
        pn = dm_block_data(parent);
        location = cpu_to_le64(dm_block_location(left));
        __dm_bless_for_disk(&location);
-       memcpy_disk(value_ptr(pn, parent_index, sizeof(__le64)),
+       memcpy_disk(value_ptr(pn, parent_index),
                    &location, sizeof(__le64));
 
        location = cpu_to_le64(dm_block_location(right));
@@ -529,8 +528,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
                sizeof(__le64) : s->info->value_type.size;
-       memcpy(value_ptr(ln, 0, size), value_ptr(pn, 0, size), nr_left * size);
-       memcpy(value_ptr(rn, 0, size), value_ptr(pn, nr_left, size),
+       memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
+       memcpy(value_ptr(rn, 0), value_ptr(pn, nr_left),
               nr_right * size);
 
        /* new_parent should just point to l and r now */
@@ -545,12 +544,12 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
        val = cpu_to_le64(dm_block_location(left));
        __dm_bless_for_disk(&val);
        pn->keys[0] = ln->keys[0];
-       memcpy_disk(value_ptr(pn, 0, sizeof(__le64)), &val, sizeof(__le64));
+       memcpy_disk(value_ptr(pn, 0), &val, sizeof(__le64));
 
        val = cpu_to_le64(dm_block_location(right));
        __dm_bless_for_disk(&val);
        pn->keys[1] = rn->keys[0];
-       memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
+       memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64));
 
        /*
         * rejig the spine.  This is ugly, since it knows too
@@ -595,7 +594,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
                        __le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
 
                        __dm_bless_for_disk(&location);
-                       memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(uint64_t)),
+                       memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i),
                                    &location, sizeof(__le64));
                }
 
@@ -710,12 +709,12 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
                    (!info->value_type.equal ||
                     !info->value_type.equal(
                             info->value_type.context,
-                            value_ptr(n, index, info->value_type.size),
+                            value_ptr(n, index),
                             value))) {
                        info->value_type.dec(info->value_type.context,
-                                            value_ptr(n, index, info->value_type.size));
+                                            value_ptr(n, index));
                }
-               memcpy_disk(value_ptr(n, index, info->value_type.size),
+               memcpy_disk(value_ptr(n, index),
                            value, info->value_type.size);
        }
 
index df2494c06cdc08acc566dcaef7e12f14689224ac..ff3beed6ad2d93769e475539ecd60d29ffdfaf22 100644 (file)
@@ -405,8 +405,6 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
                if (r < 0)
                        return r;
 
-#if 0
-               /* FIXME: dm_btree_remove doesn't handle this yet */
                if (old > 2) {
                        r = dm_btree_remove(&ll->ref_count_info,
                                            ll->ref_count_root,
@@ -414,7 +412,6 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
                        if (r)
                                return r;
                }
-#endif
 
        } else {
                __le32 le_rc = cpu_to_le32(ref_count);
index e4b5c03ae516a4900c2aef889eeae40677e222e6..73970cd97af1356e1fdeaea9dd733aab94a5f5c7 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/ioctl.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include "dmxdev.h"
 
 static int debug;
index 864b6274c72901b9f02323138355a0a44869baea..e24ec539a5fde6dee6c96489c97199ca6232fd90 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/workqueue.h>
 
 #include <asm/page.h>
-#include <asm/system.h>
 
 #include <dvb_demux.h>
 
index 6ecbcf614878fa186be24be1a39f8a07365b3cc9..4bd8bd56befc2230d739c89c7deea63b0644bd25 100644 (file)
@@ -53,7 +53,6 @@
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 
-#include <asm/system.h>
 
 #include <linux/dvb/frontend.h>
 
index 421cf73858d3434574c2168866be5a61af49bf0b..f6b52d5494309cb0b3829916136d8352fc57adc1 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include <media/media-devnode.h>
 
index d6488b79ae3b54602e09170372b03bbbe8f3929a..bba299dbf3967c6e7e708f9631eb9853912d1833 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/clk.h>
 #include <linux/slab.h>
 
-#include <mach/io.h>
 #include <mach/cputype.h>
 #include <mach/hardware.h>
 
index 00e80f59d5d5339c6f0e835e9f82103d328be7f5..b21ecc8d134d2bffa5794c6e6cc51477074a5ca5 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <mach/hardware.h>
 #include <mach/mux.h>
-#include <mach/io.h>
 #include <mach/i2c.h>
 
 #include <linux/io.h>
index f767df9439548cb9e21023997b243c4f0308e6a0..2e220028aad2f383417904ce9d629d5bb4857d4e 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <linux/dvb/video.h>
index 74522773e934c18e417f36b36aed40017b35e02f..93c35ef5f0adc30dc89831c55cd425e69db7c756 100644 (file)
@@ -286,7 +286,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
                sg_dma_address(sg)      = vb2_dma_contig_plane_dma_addr(vb, 0);
                sg_dma_len(sg)          = new_size;
 
-               txd = ichan->dma_chan.device->device_prep_slave_sg(
+               txd = dmaengine_prep_slave_sg(
                        &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT);
                if (!txd)
index 4ed1c7c28ae704b4f1e843cb8db0ae7b74981c02..02194c056b005f601d5d6743221f38c7f67971ab 100644 (file)
@@ -564,7 +564,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 
        spin_unlock_irq(&fh->queue_lock);
 
-       desc = fh->chan->device->device_prep_slave_sg(fh->chan,
+       desc = dmaengine_prep_slave_sg(fh->chan,
                buf->sg, sg_elems, DMA_DEV_TO_MEM,
                DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
        if (!desc) {
index 5c6100fb4072120072d0301ca366ddbb8bf5ed93..1baec8393306de0c1c781c88987615a24701c91f 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/spi/spi.h>
 #endif
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/div64.h>
index 041804b73ebdffc1f95fe744f6aa68b8aecb9acc..70bec548d9048c6524702e1a5e028d96db437ad1 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
index c8ed7b63fdf5e2dda7d2fb13463d18db2223feec..1d31d7284cbd0b3e0de425ff5c56dd22677fb24a 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/scatterlist.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 
index 17dfe9bb6d2745c2bb5f6123b1afbc6c6d997ca6..87bd5ba38d5b649db355f252d326fe28116041c0 100644 (file)
@@ -503,6 +503,101 @@ static void device_irq_exit(struct pm860x_chip *chip)
                free_irq(chip->core_irq, chip);
 }
 
+int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client)
+{
+       int ret = -EIO;
+       struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
+               chip->client : chip->companion;
+
+       dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
+       dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status);
+
+       mutex_lock(&chip->osc_lock);
+       /* Update voting status */
+       chip->osc_vote |= client;
+       /* If reference group is off - turn on*/
+       if (chip->osc_status != PM8606_REF_GP_OSC_ON) {
+               chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
+               /* Enable Reference group Vsys */
+               if (pm860x_set_bits(i2c, PM8606_VSYS,
+                               PM8606_VSYS_EN, PM8606_VSYS_EN))
+                       goto out;
+
+               /*Enable Internal Oscillator */
+               if (pm860x_set_bits(i2c, PM8606_MISC,
+                               PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN))
+                       goto out;
+               /* Update status (only if writes succeed) */
+               chip->osc_status = PM8606_REF_GP_OSC_ON;
+       }
+       mutex_unlock(&chip->osc_lock);
+
+       dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status, ret);
+       return 0;
+out:
+       mutex_unlock(&chip->osc_lock);
+       return ret;
+}
+EXPORT_SYMBOL(pm8606_osc_enable);
+
+int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
+{
+       int ret = -EIO;
+       struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
+               chip->client : chip->companion;
+
+       dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
+       dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status);
+
+       mutex_lock(&chip->osc_lock);
+       /*Update voting status */
+       chip->osc_vote &= ~(client);
+       /* If reference group is off and this is the last client to release
+        * - turn off */
+       if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
+                       (chip->osc_vote == REF_GP_NO_CLIENTS)) {
+               chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
+               /* Disable Reference group Vsys */
+               if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0))
+                       goto out;
+               /* Disable Internal Oscillator */
+               if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0))
+                       goto out;
+               chip->osc_status = PM8606_REF_GP_OSC_OFF;
+       }
+       mutex_unlock(&chip->osc_lock);
+
+       dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status, ret);
+       return 0;
+out:
+       mutex_unlock(&chip->osc_lock);
+       return ret;
+}
+EXPORT_SYMBOL(pm8606_osc_disable);
+
+static void __devinit device_osc_init(struct i2c_client *i2c)
+{
+       struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+
+       mutex_init(&chip->osc_lock);
+       /* init portofino reference group voting and status */
+       /* Disable Reference group Vsys */
+       pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0);
+       /* Disable Internal Oscillator */
+       pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0);
+
+       chip->osc_vote = REF_GP_NO_CLIENTS;
+       chip->osc_status = PM8606_REF_GP_OSC_OFF;
+}
+
 static void __devinit device_bk_init(struct pm860x_chip *chip,
                                     struct pm860x_platform_data *pdata)
 {
@@ -767,6 +862,15 @@ out:
        return;
 }
 
+static void __devinit device_8606_init(struct pm860x_chip *chip,
+                                      struct i2c_client *i2c,
+                                      struct pm860x_platform_data *pdata)
+{
+       device_osc_init(i2c);
+       device_bk_init(chip, pdata);
+       device_led_init(chip, pdata);
+}
+
 int __devinit pm860x_device_init(struct pm860x_chip *chip,
                       struct pm860x_platform_data *pdata)
 {
@@ -774,8 +878,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
 
        switch (chip->id) {
        case CHIP_PM8606:
-               device_bk_init(chip, pdata);
-               device_led_init(chip, pdata);
+               device_8606_init(chip, chip->client, pdata);
                break;
        case CHIP_PM8607:
                device_8607_init(chip, chip->client, pdata);
@@ -785,8 +888,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
        if (chip->companion) {
                switch (chip->id) {
                case CHIP_PM8607:
-                       device_bk_init(chip, pdata);
-                       device_led_init(chip, pdata);
+                       device_8606_init(chip, chip->companion, pdata);
                        break;
                case CHIP_PM8606:
                        device_8607_init(chip, chip->companion, pdata);
index f93dd9571c3c81e8b44f26dc51d54b0901039cd6..b2cfdc458561fb5fcba59a6dc11e0a9b70c6b55a 100644 (file)
@@ -334,10 +334,35 @@ static int __devexit pm860x_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev) && chip->wakeup_flag)
+               enable_irq_wake(chip->core_irq);
+       return 0;
+}
+
+static int pm860x_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev) && chip->wakeup_flag)
+               disable_irq_wake(chip->core_irq);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
+
 static struct i2c_driver pm860x_driver = {
        .driver = {
                .name   = "88PM860x",
                .owner  = THIS_MODULE,
+               .pm     = &pm860x_pm_ops,
        },
        .probe          = pm860x_probe,
        .remove         = __devexit_p(pm860x_remove),
index 243e0c663c37be28fc2282dc98be2e9715f7804a..29f463cc09cbc5dc56ec215a225548be8a65b900 100644 (file)
@@ -143,6 +143,21 @@ config TPS6507X
          This driver can also be built as a module.  If so, the module
          will be called tps6507x.
 
+config MFD_TPS65217
+       tristate "TPS65217 Power Management / White LED chips"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the TPS65217 series of
+         Power Management / White LED chips.
+         These include voltage regulators, lithium ion/polymer battery
+         charger, wled and other features that are often used in portable
+         devices.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps65217.
+
 config MFD_TPS6586X
        bool "TPS6586x Power Management chips"
        depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS
@@ -162,6 +177,7 @@ config MFD_TPS65910
        depends on I2C=y && GPIOLIB
        select MFD_CORE
        select GPIO_TPS65910
+       select REGMAP_I2C
        help
          if you say yes here you get support for the TPS65910 series of
          Power Management chips.
@@ -171,7 +187,7 @@ config MFD_TPS65912
        depends on GPIOLIB
 
 config MFD_TPS65912_I2C
-       bool "TPS95612 Power Management chip with I2C"
+       bool "TPS65912 Power Management chip with I2C"
        select MFD_CORE
        select MFD_TPS65912
        depends on I2C=y && GPIOLIB
@@ -400,7 +416,7 @@ config MFD_MAX8997
        depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
        help
-         Say yes here to support for Maxim Semiconductor MAX8998/8966.
+         Say yes here to support for Maxim Semiconductor MAX8997/8966.
          This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
          MUIC controls on chip.
          This driver provides common support for accessing the device;
@@ -812,6 +828,18 @@ config MFD_PM8XXX_IRQ
 config TPS65911_COMPARATOR
        tristate
 
+config MFD_TPS65090
+       bool "TPS65090 Power Management chips"
+       depends on I2C=y && GENERIC_HARDIRQS
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the TPS65090 series of
+         Power Management chips.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
 config MFD_AAT2870_CORE
        bool "Support for the AnalogicTech AAT2870"
        select MFD_CORE
@@ -831,6 +859,28 @@ config MFD_INTEL_MSIC
          Passage) chip. This chip embeds audio, battery, GPIO, etc.
          devices used in Intel Medfield platforms.
 
+config MFD_RC5T583
+       bool "Ricoh RC5T583 Power Management system device"
+       depends on I2C=y && GENERIC_HARDIRQS
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Select this option to get support for the RICOH583 Power
+         Management system device.
+         This driver provides common support for accessing the device
+         through i2c interface. The device supports multiple sub-devices
+         like GPIO, interrupts, RTC, LDO and DCDC regulators, onkey.
+         Additional drivers must be enabled in order to use the
+         different functionality of the device.
+
+config MFD_ANATOP
+       bool "Support for Freescale i.MX on-chip ANATOP controller"
+       depends on SOC_IMX6Q
+       help
+         Select this option to enable Freescale i.MX on-chip ANATOP
+         MFD controller. This controller embeds regulator and
+         thermal devices for Freescale i.MX platforms.
+
 endmenu
 endif
 
index b953bab934f7f872a7f53307a865a7efa22312ac..05fa538c5efe942ebd5146e57689fc607a34955c 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_MFD_WM8994)      += wm8994-core.o wm8994-irq.o wm8994-regmap.o
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65217)     += tps65217.o
 obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
 tps65912-objs                   := tps65912-core.o tps65912-irq.o
 obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
@@ -109,6 +110,9 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST)     += omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
+obj-$(CONFIG_MFD_TPS65090)     += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
 obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
+obj-$(CONFIG_MFD_RC5T583)      += rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_S5M_CORE)     += s5m-core.o s5m-irq.o
+obj-$(CONFIG_MFD_ANATOP)       += anatop-mfd.o
index d295941c9a3db63ab75408470ac8edfefbdb2cb2..1f08704f7ae8ecab27c3247d4009f0c71de91b83 100644 (file)
@@ -32,6 +32,7 @@
 #define AB8500_IT_SOURCE6_REG          0x05
 #define AB8500_IT_SOURCE7_REG          0x06
 #define AB8500_IT_SOURCE8_REG          0x07
+#define AB9540_IT_SOURCE13_REG         0x0C
 #define AB8500_IT_SOURCE19_REG         0x12
 #define AB8500_IT_SOURCE20_REG         0x13
 #define AB8500_IT_SOURCE21_REG         0x14
@@ -53,6 +54,7 @@
 #define AB8500_IT_LATCH9_REG           0x28
 #define AB8500_IT_LATCH10_REG          0x29
 #define AB8500_IT_LATCH12_REG          0x2B
+#define AB9540_IT_LATCH13_REG          0x2C
 #define AB8500_IT_LATCH19_REG          0x32
 #define AB8500_IT_LATCH20_REG          0x33
 #define AB8500_IT_LATCH21_REG          0x34
 #define AB8500_IT_MASK24_REG           0x57
 
 #define AB8500_REV_REG                 0x80
+#define AB8500_IC_NAME_REG             0x82
 #define AB8500_SWITCH_OFF_STATUS       0x00
 
 #define AB8500_TURN_ON_STATUS          0x00
 
+#define AB9540_MODEM_CTRL2_REG                 0x23
+#define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT       BIT(2)
+
 /*
  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
- * numbers are indexed into this array with (num / 8).
+ * numbers are indexed into this array with (num / 8). The interupts are
+ * defined in linux/mfd/ab8500.h
  *
  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
  * offset 0.
  */
+/* AB8500 support */
 static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
        0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
 };
 
+/* AB9540 support */
+static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
+       0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
+};
+
+static const char ab8500_version_str[][7] = {
+       [AB8500_VERSION_AB8500] = "AB8500",
+       [AB8500_VERSION_AB8505] = "AB8505",
+       [AB8500_VERSION_AB9540] = "AB9540",
+       [AB8500_VERSION_AB8540] = "AB8540",
+};
+
 static int ab8500_get_chip_id(struct device *dev)
 {
        struct ab8500 *ab8500;
@@ -127,9 +147,7 @@ static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
 
        dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
 
-       ret = mutex_lock_interruptible(&ab8500->lock);
-       if (ret)
-               return ret;
+       mutex_lock(&ab8500->lock);
 
        ret = ab8500->write(ab8500, addr, data);
        if (ret < 0)
@@ -156,9 +174,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
         * bank on higher 8 bits and reg in lower */
        u16 addr = ((u16)bank) << 8 | reg;
 
-       ret = mutex_lock_interruptible(&ab8500->lock);
-       if (ret)
-               return ret;
+       mutex_lock(&ab8500->lock);
 
        ret = ab8500->read(ab8500, addr);
        if (ret < 0)
@@ -185,31 +201,38 @@ static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
        u8 reg, u8 bitmask, u8 bitvalues)
 {
        int ret;
-       u8 data;
        /* put the u8 bank and u8 reg together into a an u16.
         * bank on higher 8 bits and reg in lower */
        u16 addr = ((u16)bank) << 8 | reg;
 
-       ret = mutex_lock_interruptible(&ab8500->lock);
-       if (ret)
-               return ret;
+       mutex_lock(&ab8500->lock);
 
-       ret = ab8500->read(ab8500, addr);
-       if (ret < 0) {
-               dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
-                       addr, ret);
-               goto out;
-       }
+       if (ab8500->write_masked == NULL) {
+               u8 data;
 
-       data = (u8)ret;
-       data = (~bitmask & data) | (bitmask & bitvalues);
+               ret = ab8500->read(ab8500, addr);
+               if (ret < 0) {
+                       dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
+                               addr, ret);
+                       goto out;
+               }
 
-       ret = ab8500->write(ab8500, addr, data);
-       if (ret < 0)
-               dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
-                       addr, ret);
+               data = (u8)ret;
+               data = (~bitmask & data) | (bitmask & bitvalues);
+
+               ret = ab8500->write(ab8500, addr, data);
+               if (ret < 0)
+                       dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
+                               addr, ret);
 
-       dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data);
+               dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
+                       data);
+               goto out;
+       }
+       ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
+       if (ret < 0)
+               dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
+                       ret);
 out:
        mutex_unlock(&ab8500->lock);
        return ret;
@@ -248,7 +271,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
        struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
        int i;
 
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
+       for (i = 0; i < ab8500->mask_size; i++) {
                u8 old = ab8500->oldmask[i];
                u8 new = ab8500->mask[i];
                int reg;
@@ -256,14 +279,17 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
                if (new == old)
                        continue;
 
-               /* Interrupt register 12 doesn't exist prior to version 2.0 */
-               if (ab8500_irq_regoffset[i] == 11 &&
-                       ab8500->chip_id < AB8500_CUT2P0)
+               /*
+                * Interrupt register 12 doesn't exist prior to AB8500 version
+                * 2.0
+                */
+               if (ab8500->irq_reg_offset[i] == 11 &&
+                       is_ab8500_1p1_or_earlier(ab8500))
                        continue;
 
                ab8500->oldmask[i] = new;
 
-               reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
+               reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
                set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
        }
 
@@ -306,13 +332,16 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
 
        dev_vdbg(ab8500->dev, "interrupt\n");
 
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
-               int regoffset = ab8500_irq_regoffset[i];
+       for (i = 0; i < ab8500->mask_size; i++) {
+               int regoffset = ab8500->irq_reg_offset[i];
                int status;
                u8 value;
 
-               /* Interrupt register 12 doesn't exist prior to version 2.0 */
-               if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0)
+               /*
+                * Interrupt register 12 doesn't exist prior to AB8500 version
+                * 2.0
+                */
+               if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
                        continue;
 
                status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
@@ -336,8 +365,16 @@ static int ab8500_irq_init(struct ab8500 *ab8500)
 {
        int base = ab8500->irq_base;
        int irq;
+       int num_irqs;
+
+       if (is_ab9540(ab8500))
+               num_irqs = AB9540_NR_IRQS;
+       else if (is_ab8505(ab8500))
+               num_irqs = AB8505_NR_IRQS;
+       else
+               num_irqs = AB8500_NR_IRQS;
 
-       for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
+       for (irq = base; irq < base + num_irqs; irq++) {
                irq_set_chip_data(irq, ab8500);
                irq_set_chip_and_handler(irq, &ab8500_irq_chip,
                                         handle_simple_irq);
@@ -356,8 +393,16 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
 {
        int base = ab8500->irq_base;
        int irq;
+       int num_irqs;
 
-       for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
+       if (is_ab9540(ab8500))
+               num_irqs = AB9540_NR_IRQS;
+       else if (is_ab8505(ab8500))
+               num_irqs = AB8505_NR_IRQS;
+       else
+               num_irqs = AB8500_NR_IRQS;
+
+       for (irq = base; irq < base + num_irqs; irq++) {
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
@@ -366,6 +411,7 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
        }
 }
 
+/* AB8500 GPIO Resources */
 static struct resource __devinitdata ab8500_gpio_resources[] = {
        {
                .name   = "GPIO_INT6",
@@ -375,6 +421,28 @@ static struct resource __devinitdata ab8500_gpio_resources[] = {
        }
 };
 
+/* AB9540 GPIO Resources */
+static struct resource __devinitdata ab9540_gpio_resources[] = {
+       {
+               .name   = "GPIO_INT6",
+               .start  = AB8500_INT_GPIO6R,
+               .end    = AB8500_INT_GPIO41F,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "GPIO_INT14",
+               .start  = AB9540_INT_GPIO50R,
+               .end    = AB9540_INT_GPIO54R,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "GPIO_INT15",
+               .start  = AB9540_INT_GPIO50F,
+               .end    = AB9540_INT_GPIO54F,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
 static struct resource __devinitdata ab8500_gpadc_resources[] = {
        {
                .name   = "HW_CONV_END",
@@ -490,12 +558,6 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
                .end = AB8500_INT_USB_LINK_STATUS,
                .flags = IORESOURCE_IRQ,
        },
-       {
-               .name = "USB_CHARGE_DET_DONE",
-               .start = AB8500_INT_USB_CHG_DET_DONE,
-               .end = AB8500_INT_USB_CHG_DET_DONE,
-               .flags = IORESOURCE_IRQ,
-       },
        {
                .name = "VBUS_OVV",
                .start = AB8500_INT_VBUS_OVV,
@@ -534,14 +596,8 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
        },
        {
                .name = "USB_CHARGER_NOT_OKR",
-               .start = AB8500_INT_USB_CHARGER_NOT_OK,
-               .end = AB8500_INT_USB_CHARGER_NOT_OK,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "USB_CHARGER_NOT_OKF",
-               .start = AB8500_INT_USB_CHARGER_NOT_OKF,
-               .end = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .start = AB8500_INT_USB_CHARGER_NOT_OKR,
+               .end = AB8500_INT_USB_CHARGER_NOT_OKR,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -616,6 +672,12 @@ static struct resource __devinitdata ab8500_fg_resources[] = {
                .end = AB8500_INT_CC_INT_CALIB,
                .flags = IORESOURCE_IRQ,
        },
+       {
+               .name = "CCEOC",
+               .start = AB8500_INT_CCEOC,
+               .end = AB8500_INT_CCEOC,
+               .flags = IORESOURCE_IRQ,
+       },
 };
 
 static struct resource __devinitdata ab8500_chargalg_resources[] = {};
@@ -630,8 +692,8 @@ static struct resource __devinitdata ab8500_debug_resources[] = {
        },
        {
                .name   = "IRQ_LAST",
-               .start  = AB8500_INT_USB_CHARGER_NOT_OKF,
-               .end    = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .start  = AB8500_INT_XTAL32K_KO,
+               .end    = AB8500_INT_XTAL32K_KO,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -691,7 +753,7 @@ static struct resource __devinitdata ab8500_temp_resources[] = {
        },
 };
 
-static struct mfd_cell __devinitdata ab8500_devs[] = {
+static struct mfd_cell __devinitdata abx500_common_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -705,11 +767,6 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
        {
                .name = "ab8500-regulator",
        },
-       {
-               .name = "ab8500-gpio",
-               .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
-               .resources = ab8500_gpio_resources,
-       },
        {
                .name = "ab8500-gpadc",
                .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
@@ -748,11 +805,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
        {
                .name = "ab8500-codec",
        },
-       {
-               .name = "ab8500-usb",
-               .num_resources = ARRAY_SIZE(ab8500_usb_resources),
-               .resources = ab8500_usb_resources,
-       },
+
        {
                .name = "ab8500-poweron-key",
                .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
@@ -781,6 +834,32 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
        },
 };
 
+static struct mfd_cell __devinitdata ab8500_devs[] = {
+       {
+               .name = "ab8500-gpio",
+               .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
+               .resources = ab8500_gpio_resources,
+       },
+       {
+               .name = "ab8500-usb",
+               .num_resources = ARRAY_SIZE(ab8500_usb_resources),
+               .resources = ab8500_usb_resources,
+       },
+};
+
+static struct mfd_cell __devinitdata ab9540_devs[] = {
+       {
+               .name = "ab8500-gpio",
+               .num_resources = ARRAY_SIZE(ab9540_gpio_resources),
+               .resources = ab9540_gpio_resources,
+       },
+       {
+               .name = "ab9540-usb",
+               .num_resources = ARRAY_SIZE(ab8500_usb_resources),
+               .resources = ab8500_usb_resources,
+       },
+};
+
 static ssize_t show_chip_id(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -842,9 +921,64 @@ static ssize_t show_turn_on_status(struct device *dev,
        return sprintf(buf, "%#x\n", value);
 }
 
+static ssize_t show_ab9540_dbbrstn(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct ab8500 *ab8500;
+       int ret;
+       u8 value;
+
+       ab8500 = dev_get_drvdata(dev);
+
+       ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
+               AB9540_MODEM_CTRL2_REG, &value);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n",
+                       (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
+}
+
+static ssize_t store_ab9540_dbbrstn(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct ab8500 *ab8500;
+       int ret = count;
+       int err;
+       u8 bitvalues;
+
+       ab8500 = dev_get_drvdata(dev);
+
+       if (count > 0) {
+               switch (buf[0]) {
+               case '0':
+                       bitvalues = 0;
+                       break;
+               case '1':
+                       bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
+                       break;
+               default:
+                       goto exit;
+               }
+
+               err = mask_and_set_register_interruptible(ab8500,
+                       AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
+                       AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
+               if (err)
+                       dev_info(ab8500->dev,
+                               "Failed to set DBBRSTN %c, err %#x\n",
+                               buf[0], err);
+       }
+
+exit:
+       return ret;
+}
+
 static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
 static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
 static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
+static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
+                       show_ab9540_dbbrstn, store_ab9540_dbbrstn);
 
 static struct attribute *ab8500_sysfs_entries[] = {
        &dev_attr_chip_id.attr,
@@ -853,11 +987,23 @@ static struct attribute *ab8500_sysfs_entries[] = {
        NULL,
 };
 
+static struct attribute *ab9540_sysfs_entries[] = {
+       &dev_attr_chip_id.attr,
+       &dev_attr_switch_off_status.attr,
+       &dev_attr_turn_on_status.attr,
+       &dev_attr_dbbrstn.attr,
+       NULL,
+};
+
 static struct attribute_group ab8500_attr_group = {
        .attrs  = ab8500_sysfs_entries,
 };
 
-int __devinit ab8500_init(struct ab8500 *ab8500)
+static struct attribute_group ab9540_attr_group = {
+       .attrs  = ab9540_sysfs_entries,
+};
+
+int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
 {
        struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
        int ret;
@@ -870,25 +1016,45 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
        mutex_init(&ab8500->lock);
        mutex_init(&ab8500->irq_lock);
 
+       if (version != AB8500_VERSION_UNDEFINED)
+               ab8500->version = version;
+       else {
+               ret = get_register_interruptible(ab8500, AB8500_MISC,
+                       AB8500_IC_NAME_REG, &value);
+               if (ret < 0)
+                       return ret;
+
+               ab8500->version = value;
+       }
+
        ret = get_register_interruptible(ab8500, AB8500_MISC,
                AB8500_REV_REG, &value);
        if (ret < 0)
                return ret;
 
-       switch (value) {
-       case AB8500_CUT1P0:
-       case AB8500_CUT1P1:
-       case AB8500_CUT2P0:
-       case AB8500_CUT3P0:
-       case AB8500_CUT3P3:
-               dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
-               break;
-       default:
-               dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
-               return -EINVAL;
-       }
        ab8500->chip_id = value;
 
+       dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
+                       ab8500_version_str[ab8500->version],
+                       ab8500->chip_id >> 4,
+                       ab8500->chip_id & 0x0F);
+
+       /* Configure AB8500 or AB9540 IRQ */
+       if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
+               ab8500->mask_size = AB9540_NUM_IRQ_REGS;
+               ab8500->irq_reg_offset = ab9540_irq_regoffset;
+       } else {
+               ab8500->mask_size = AB8500_NUM_IRQ_REGS;
+               ab8500->irq_reg_offset = ab8500_irq_regoffset;
+       }
+       ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
+       if (!ab8500->mask)
+               return -ENOMEM;
+       ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
+       if (!ab8500->oldmask) {
+               ret = -ENOMEM;
+               goto out_freemask;
+       }
        /*
         * ab8500 has switched off due to (SWITCH_OFF_STATUS):
         * 0x01 Swoff bit programming
@@ -911,30 +1077,33 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
                plat->init(ab8500);
 
        /* Clear and mask all interrupts */
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
-               /* Interrupt register 12 doesn't exist prior to version 2.0 */
-               if (ab8500_irq_regoffset[i] == 11 &&
-                       ab8500->chip_id < AB8500_CUT2P0)
+       for (i = 0; i < ab8500->mask_size; i++) {
+               /*
+                * Interrupt register 12 doesn't exist prior to AB8500 version
+                * 2.0
+                */
+               if (ab8500->irq_reg_offset[i] == 11 &&
+                               is_ab8500_1p1_or_earlier(ab8500))
                        continue;
 
                get_register_interruptible(ab8500, AB8500_INTERRUPT,
-                       AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i],
+                       AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
                        &value);
                set_register_interruptible(ab8500, AB8500_INTERRUPT,
-                       AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i], 0xff);
+                       AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
        }
 
        ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
        if (ret)
-               return ret;
+               goto out_freeoldmask;
 
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++)
+       for (i = 0; i < ab8500->mask_size; i++)
                ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
 
        if (ab8500->irq_base) {
                ret = ab8500_irq_init(ab8500);
                if (ret)
-                       return ret;
+                       goto out_freeoldmask;
 
                ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
                                           IRQF_ONESHOT | IRQF_NO_SUSPEND,
@@ -943,17 +1112,34 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
                        goto out_removeirq;
        }
 
-       ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
-                             ARRAY_SIZE(ab8500_devs), NULL,
+       ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
+                             ARRAY_SIZE(abx500_common_devs), NULL,
                              ab8500->irq_base);
+
        if (ret)
                goto out_freeirq;
 
-       ret = sysfs_create_group(&ab8500->dev->kobj, &ab8500_attr_group);
+       if (is_ab9540(ab8500))
+               ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
+                             ARRAY_SIZE(ab9540_devs), NULL,
+                             ab8500->irq_base);
+       else
+               ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
+                             ARRAY_SIZE(ab9540_devs), NULL,
+                             ab8500->irq_base);
        if (ret)
-               dev_err(ab8500->dev, "error creating sysfs entries\n");
+               goto out_freeirq;
 
-       return ret;
+       if (is_ab9540(ab8500))
+               ret = sysfs_create_group(&ab8500->dev->kobj,
+                                       &ab9540_attr_group);
+       else
+               ret = sysfs_create_group(&ab8500->dev->kobj,
+                                       &ab8500_attr_group);
+       if (ret)
+               dev_err(ab8500->dev, "error creating sysfs entries\n");
+       else
+               return ret;
 
 out_freeirq:
        if (ab8500->irq_base)
@@ -961,18 +1147,27 @@ out_freeirq:
 out_removeirq:
        if (ab8500->irq_base)
                ab8500_irq_remove(ab8500);
+out_freeoldmask:
+       kfree(ab8500->oldmask);
+out_freemask:
+       kfree(ab8500->mask);
 
        return ret;
 }
 
 int __devexit ab8500_exit(struct ab8500 *ab8500)
 {
-       sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
+       if (is_ab9540(ab8500))
+               sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
+       else
+               sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
        mfd_remove_devices(ab8500->dev);
        if (ab8500->irq_base) {
                free_irq(ab8500->irq, ab8500);
                ab8500_irq_remove(ab8500);
        }
+       kfree(ab8500->oldmask);
+       kfree(ab8500->mask);
 
        return 0;
 }
index 087fecd71ce032b2ad459467c02aef47197f13ea..b83045f102bed1c93251b41716f4ffc06f8f88f1 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 
 static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
 {
@@ -23,6 +23,18 @@ static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
        return ret;
 }
 
+static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
+       u8 data)
+{
+       int ret;
+
+       ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
+               &mask, 1);
+       if (ret < 0)
+               dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
+       return ret;
+}
+
 static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr)
 {
        int ret;
@@ -38,6 +50,7 @@ static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr)
 
 static int __devinit ab8500_i2c_probe(struct platform_device *plf)
 {
+       const struct platform_device_id *platid = platform_get_device_id(plf);
        struct ab8500 *ab8500;
        struct resource *resource;
        int ret;
@@ -58,13 +71,15 @@ static int __devinit ab8500_i2c_probe(struct platform_device *plf)
 
        ab8500->read = ab8500_i2c_read;
        ab8500->write = ab8500_i2c_write;
+       ab8500->write_masked = ab8500_i2c_write_masked;
 
        platform_set_drvdata(plf, ab8500);
 
-       ret = ab8500_init(ab8500);
+       ret = ab8500_init(ab8500, platid->driver_data);
        if (ret)
                kfree(ab8500);
 
+
        return ret;
 }
 
@@ -78,13 +93,22 @@ static int __devexit ab8500_i2c_remove(struct platform_device *plf)
        return 0;
 }
 
+static const struct platform_device_id ab8500_id[] = {
+       { "ab8500-i2c", AB8500_VERSION_AB8500 },
+       { "ab8505-i2c", AB8500_VERSION_AB8505 },
+       { "ab9540-i2c", AB8500_VERSION_AB9540 },
+       { "ab8540-i2c", AB8500_VERSION_AB8540 },
+       { }
+};
+
 static struct platform_driver ab8500_i2c_driver = {
        .driver = {
                .name = "ab8500-i2c",
                .owner = THIS_MODULE,
        },
        .probe  = ab8500_i2c_probe,
-       .remove = __devexit_p(ab8500_i2c_remove)
+       .remove = __devexit_p(ab8500_i2c_remove),
+       .id_table = ab8500_id,
 };
 
 static int __init ab8500_i2c_init(void)
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
new file mode 100644 (file)
index 0000000..2af4248
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/mfd/anatop.h>
+
+u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift,
+                   int bit_width)
+{
+       u32 val, mask;
+
+       if (bit_width == 32)
+               mask = ~0;
+       else
+               mask = (1 << bit_width) - 1;
+
+       val = readl(adata->ioreg + addr);
+       val = (val >> bit_shift) & mask;
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(anatop_get_bits);
+
+void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
+                    int bit_width, u32 data)
+{
+       u32 val, mask;
+
+       if (bit_width == 32)
+               mask = ~0;
+       else
+               mask = (1 << bit_width) - 1;
+
+       spin_lock(&adata->reglock);
+       val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
+       writel((data << bit_shift) | val, adata->ioreg + addr);
+       spin_unlock(&adata->reglock);
+}
+EXPORT_SYMBOL_GPL(anatop_set_bits);
+
+static const struct of_device_id of_anatop_match[] = {
+       { .compatible = "fsl,imx6q-anatop", },
+       { },
+};
+
+static int __devinit of_anatop_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       void *ioreg;
+       struct anatop *drvdata;
+
+       ioreg = of_iomap(np, 0);
+       if (!ioreg)
+               return -EADDRNOTAVAIL;
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+       drvdata->ioreg = ioreg;
+       spin_lock_init(&drvdata->reglock);
+       platform_set_drvdata(pdev, drvdata);
+       of_platform_populate(np, of_anatop_match, NULL, dev);
+
+       return 0;
+}
+
+static int __devexit of_anatop_remove(struct platform_device *pdev)
+{
+       struct anatop *drvdata;
+       drvdata = platform_get_drvdata(pdev);
+       iounmap(drvdata->ioreg);
+
+       return 0;
+}
+
+static struct platform_driver anatop_of_driver = {
+       .driver = {
+               .name = "anatop-mfd",
+               .owner = THIS_MODULE,
+               .of_match_table = of_anatop_match,
+       },
+       .probe          = of_anatop_probe,
+       .remove         = of_anatop_remove,
+};
+
+static int __init anatop_init(void)
+{
+       return platform_driver_register(&anatop_of_driver);
+}
+postcore_initcall(anatop_init);
+
+static void __exit anatop_exit(void)
+{
+       platform_driver_unregister(&anatop_of_driver);
+}
+module_exit(anatop_exit);
+
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_DESCRIPTION("ANATOP MFD driver");
+MODULE_LICENSE("GPL v2");
index b85bbd7f0d1980f16e78a49cae46658b1158627b..1895cf9fab8c1b1c491cbc611335775f014760e0 100644 (file)
@@ -525,6 +525,11 @@ static void asic3_gpio_set(struct gpio_chip *chip,
        return;
 }
 
+static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return (offset < ASIC3_NUM_GPIOS) ? IRQ_BOARD_START + offset : -ENXIO;
+}
+
 static __init int asic3_gpio_probe(struct platform_device *pdev,
                                   u16 *gpio_config, int num)
 {
@@ -976,6 +981,7 @@ static int __init asic3_probe(struct platform_device *pdev)
        asic->gpio.set = asic3_gpio_set;
        asic->gpio.direction_input = asic3_gpio_direction_input;
        asic->gpio.direction_output = asic3_gpio_direction_output;
+       asic->gpio.to_irq = asic3_gpio_to_irq;
 
        ret = asic3_gpio_probe(pdev,
                               pdata->gpio_config,
index 5ddde2a9176afa32a8211d2951fc36cbccc85d64..7ff313fe9fb112afd5175dc9b091d224ea936f7e 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/mutex.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -647,8 +646,6 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
        struct irq_desc *desc;
        int ret;
 
-       mutex_init(&da9052->io_lock);
-
        if (pdata && pdata->init != NULL)
                pdata->init(da9052);
 
index 44b97c70a61f9671342c2bd23aad0416e7239d25..36b88e395499f1673ecb57eee39b0c6a3fa920cd 100644 (file)
@@ -74,24 +74,27 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client,
 
        ret = da9052_i2c_enable_multiwrite(da9052);
        if (ret < 0)
-               goto err;
+               goto err_regmap;
 
        ret = da9052_device_init(da9052, id->driver_data);
        if (ret != 0)
-               goto err;
+               goto err_regmap;
 
        return 0;
 
+err_regmap:
+       regmap_exit(da9052->regmap);
 err:
        kfree(da9052);
        return ret;
 }
 
-static int da9052_i2c_remove(struct i2c_client *client)
+static int __devexit da9052_i2c_remove(struct i2c_client *client)
 {
        struct da9052 *da9052 = i2c_get_clientdata(client);
 
        da9052_device_exit(da9052);
+       regmap_exit(da9052->regmap);
        kfree(da9052);
 
        return 0;
@@ -107,7 +110,7 @@ static struct i2c_device_id da9052_i2c_id[] = {
 
 static struct i2c_driver da9052_i2c_driver = {
        .probe = da9052_i2c_probe,
-       .remove = da9052_i2c_remove,
+       .remove = __devexit_p(da9052_i2c_remove),
        .id_table = da9052_i2c_id,
        .driver = {
                .name = "da9052",
index cdbc7cad326fdb360dd081c02ced384232da8724..6faf149e8d94c8d2b90c3ef69edc6d2e98a0fa6d 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <linux/mfd/da9052/da9052.h>
 
-static int da9052_spi_probe(struct spi_device *spi)
+static int __devinit da9052_spi_probe(struct spi_device *spi)
 {
        int ret;
        const struct spi_device_id *id = spi_get_device_id(spi);
@@ -52,20 +52,23 @@ static int da9052_spi_probe(struct spi_device *spi)
 
        ret = da9052_device_init(da9052, id->driver_data);
        if (ret != 0)
-               goto err;
+               goto err_regmap;
 
        return 0;
 
+err_regmap:
+       regmap_exit(da9052->regmap);
 err:
        kfree(da9052);
        return ret;
 }
 
-static int da9052_spi_remove(struct spi_device *spi)
+static int __devexit da9052_spi_remove(struct spi_device *spi)
 {
        struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
 
        da9052_device_exit(da9052);
+       regmap_exit(da9052->regmap);
        kfree(da9052);
 
        return 0;
index af8e0efedbe477a3ba096c6678dd0a84ac948e2f..ebc1e8658226bbfca7505f2d109d119a9598e690 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
+#include <asm/hardware/gic.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db8500-regs.h>
 /* Offset for the firmware version within the TCPM */
 #define PRCMU_FW_VERSION_OFFSET 0xA4
 
-/* PRCMU project numbers, defined by PRCMU FW */
-#define PRCMU_PROJECT_ID_8500V1_0 1
-#define PRCMU_PROJECT_ID_8500V2_0 2
-#define PRCMU_PROJECT_ID_8400V2_0 3
-
 /* Index of different voltages to be used when accessing AVSData */
 #define PRCM_AVS_BASE          0x2FC
 #define PRCM_AVS_VBB_RET       (PRCM_AVS_BASE + 0x0)
 #define PRCM_REQ_MB1_ARM_OPP                   (PRCM_REQ_MB1 + 0x0)
 #define PRCM_REQ_MB1_APE_OPP                   (PRCM_REQ_MB1 + 0x1)
 #define PRCM_REQ_MB1_PLL_ON_OFF                        (PRCM_REQ_MB1 + 0x4)
+#define PLL_SOC0_OFF   0x1
+#define PLL_SOC0_ON    0x2
 #define PLL_SOC1_OFF   0x4
 #define PLL_SOC1_ON    0x8
 
 #define WAKEUP_BIT_GPIO7 BIT(30)
 #define WAKEUP_BIT_GPIO8 BIT(31)
 
+static struct {
+       bool valid;
+       struct prcmu_fw_version version;
+} fw_info;
+
 /*
  * This vector maps irq numbers to the bits in the bit field used in
  * communication with the PRCMU firmware.
@@ -341,11 +344,13 @@ static struct {
  * mb1_transfer - state needed for mailbox 1 communication.
  * @lock:      The transaction lock.
  * @work:      The transaction completion structure.
+ * @ape_opp:   The current APE OPP.
  * @ack:       Reply ("acknowledge") data.
  */
 static struct {
        struct mutex lock;
        struct completion work;
+       u8 ape_opp;
        struct {
                u8 header;
                u8 arm_opp;
@@ -413,79 +418,102 @@ static struct {
 static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
 
 /* Spinlocks */
+static DEFINE_SPINLOCK(prcmu_lock);
 static DEFINE_SPINLOCK(clkout_lock);
-static DEFINE_SPINLOCK(gpiocr_lock);
 
 /* Global var to runtime determine TCDM base for v2 or v1 */
 static __iomem void *tcdm_base;
 
 struct clk_mgt {
-       unsigned int offset;
+       void __iomem *reg;
        u32 pllsw;
+       int branch;
+       bool clk38div;
+};
+
+enum {
+       PLL_RAW,
+       PLL_FIX,
+       PLL_DIV
 };
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
-#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 }
+#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
+       { (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
 struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
-       CLK_MGT_ENTRY(SGACLK),
-       CLK_MGT_ENTRY(UARTCLK),
-       CLK_MGT_ENTRY(MSP02CLK),
-       CLK_MGT_ENTRY(MSP1CLK),
-       CLK_MGT_ENTRY(I2CCLK),
-       CLK_MGT_ENTRY(SDMMCCLK),
-       CLK_MGT_ENTRY(SLIMCLK),
-       CLK_MGT_ENTRY(PER1CLK),
-       CLK_MGT_ENTRY(PER2CLK),
-       CLK_MGT_ENTRY(PER3CLK),
-       CLK_MGT_ENTRY(PER5CLK),
-       CLK_MGT_ENTRY(PER6CLK),
-       CLK_MGT_ENTRY(PER7CLK),
-       CLK_MGT_ENTRY(LCDCLK),
-       CLK_MGT_ENTRY(BMLCLK),
-       CLK_MGT_ENTRY(HSITXCLK),
-       CLK_MGT_ENTRY(HSIRXCLK),
-       CLK_MGT_ENTRY(HDMICLK),
-       CLK_MGT_ENTRY(APEATCLK),
-       CLK_MGT_ENTRY(APETRACECLK),
-       CLK_MGT_ENTRY(MCDECLK),
-       CLK_MGT_ENTRY(IPI2CCLK),
-       CLK_MGT_ENTRY(DSIALTCLK),
-       CLK_MGT_ENTRY(DMACLK),
-       CLK_MGT_ENTRY(B2R2CLK),
-       CLK_MGT_ENTRY(TVCLK),
-       CLK_MGT_ENTRY(SSPCLK),
-       CLK_MGT_ENTRY(RNGCLK),
-       CLK_MGT_ENTRY(UICCCLK),
+       CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
+       CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false),
+       CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false),
+       CLK_MGT_ENTRY(DMACLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(TVCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false),
+};
+
+struct dsiclk {
+       u32 divsel_mask;
+       u32 divsel_shift;
+       u32 divsel;
+};
+
+static struct dsiclk dsiclk[2] = {
+       {
+               .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK,
+               .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT,
+               .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
+       },
+       {
+               .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK,
+               .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT,
+               .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
+       }
 };
 
-static struct regulator *hwacc_regulator[NUM_HW_ACC];
-static struct regulator *hwacc_ret_regulator[NUM_HW_ACC];
-
-static bool hwacc_enabled[NUM_HW_ACC];
-static bool hwacc_ret_enabled[NUM_HW_ACC];
-
-static const char *hwacc_regulator_name[NUM_HW_ACC] = {
-       [HW_ACC_SVAMMDSP]       = "hwacc-sva-mmdsp",
-       [HW_ACC_SVAPIPE]        = "hwacc-sva-pipe",
-       [HW_ACC_SIAMMDSP]       = "hwacc-sia-mmdsp",
-       [HW_ACC_SIAPIPE]        = "hwacc-sia-pipe",
-       [HW_ACC_SGA]            = "hwacc-sga",
-       [HW_ACC_B2R2]           = "hwacc-b2r2",
-       [HW_ACC_MCDE]           = "hwacc-mcde",
-       [HW_ACC_ESRAM1]         = "hwacc-esram1",
-       [HW_ACC_ESRAM2]         = "hwacc-esram2",
-       [HW_ACC_ESRAM3]         = "hwacc-esram3",
-       [HW_ACC_ESRAM4]         = "hwacc-esram4",
+struct dsiescclk {
+       u32 en;
+       u32 div_mask;
+       u32 div_shift;
 };
 
-static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
-       [HW_ACC_SVAMMDSP]       = "hwacc-sva-mmdsp-ret",
-       [HW_ACC_SIAMMDSP]       = "hwacc-sia-mmdsp-ret",
-       [HW_ACC_ESRAM1]         = "hwacc-esram1-ret",
-       [HW_ACC_ESRAM2]         = "hwacc-esram2-ret",
-       [HW_ACC_ESRAM3]         = "hwacc-esram3-ret",
-       [HW_ACC_ESRAM4]         = "hwacc-esram4-ret",
+static struct dsiescclk dsiescclk[3] = {
+       {
+               .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN,
+               .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK,
+               .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT,
+       },
+       {
+               .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN,
+               .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK,
+               .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT,
+       },
+       {
+               .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN,
+               .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK,
+               .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT,
+       }
 };
 
 /*
@@ -503,9 +531,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
 /* PLLDIV=12, PLLSW=4 (PLLDDR) */
 #define PRCMU_DSI_CLOCK_SETTING                0x0000008C
 
-/* PLLDIV=8, PLLSW=4 (PLLDDR) */
-#define PRCMU_DSI_CLOCK_SETTING_U8400  0x00000088
-
 /* DPI 50000000 Hz */
 #define PRCMU_DPI_CLOCK_SETTING                ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \
                                          (16 << PRCMU_CLK_PLL_DIV_SHIFT))
@@ -514,9 +539,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
 /* D=101, N=1, R=4, SELDIV2=0 */
 #define PRCMU_PLLDSI_FREQ_SETTING      0x00040165
 
-/* D=70, N=1, R=3, SELDIV2=0 */
-#define PRCMU_PLLDSI_FREQ_SETTING_U8400        0x00030146
-
 #define PRCMU_ENABLE_PLLDSI            0x00000001
 #define PRCMU_DISABLE_PLLDSI           0x00000000
 #define PRCMU_RELEASE_RESET_DSS                0x0000400C
@@ -528,30 +550,17 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
 
 #define PRCMU_PLLDSI_LOCKP_LOCKED      0x3
 
-static struct {
-       u8 project_number;
-       u8 api_version;
-       u8 func_version;
-       u8 errata;
-} prcmu_version;
-
-
 int db8500_prcmu_enable_dsipll(void)
 {
        int i;
-       unsigned int plldsifreq;
 
        /* Clear DSIPLL_RESETN */
        writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
        /* Unclamp DSIPLL in/out */
        writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
 
-       if (prcmu_is_u8400())
-               plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400;
-       else
-               plldsifreq = PRCMU_PLLDSI_FREQ_SETTING;
        /* Set DSI PLL FREQ */
-       writel(plldsifreq, PRCM_PLLDSI_FREQ);
+       writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ);
        writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL);
        /* Enable Escape clocks */
        writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
@@ -583,12 +592,6 @@ int db8500_prcmu_disable_dsipll(void)
 int db8500_prcmu_set_display_clocks(void)
 {
        unsigned long flags;
-       unsigned int dsiclk;
-
-       if (prcmu_is_u8400())
-               dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400;
-       else
-               dsiclk = PRCMU_DSI_CLOCK_SETTING;
 
        spin_lock_irqsave(&clk_mgt_lock, flags);
 
@@ -596,7 +599,7 @@ int db8500_prcmu_set_display_clocks(void)
        while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
-       writel(dsiclk, PRCM_HDMICLK_MGT);
+       writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT);
        writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
        writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT);
 
@@ -608,43 +611,41 @@ int db8500_prcmu_set_display_clocks(void)
        return 0;
 }
 
-/**
- * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
- */
-void prcmu_enable_spi2(void)
+u32 db8500_prcmu_read(unsigned int reg)
+{
+       return readl(_PRCMU_BASE + reg);
+}
+
+void db8500_prcmu_write(unsigned int reg, u32 value)
 {
-       u32 reg;
        unsigned long flags;
 
-       spin_lock_irqsave(&gpiocr_lock, flags);
-       reg = readl(PRCM_GPIOCR);
-       writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
-       spin_unlock_irqrestore(&gpiocr_lock, flags);
+       spin_lock_irqsave(&prcmu_lock, flags);
+       writel(value, (_PRCMU_BASE + reg));
+       spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-/**
- * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
- */
-void prcmu_disable_spi2(void)
+void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
 {
-       u32 reg;
+       u32 val;
        unsigned long flags;
 
-       spin_lock_irqsave(&gpiocr_lock, flags);
-       reg = readl(PRCM_GPIOCR);
-       writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
-       spin_unlock_irqrestore(&gpiocr_lock, flags);
+       spin_lock_irqsave(&prcmu_lock, flags);
+       val = readl(_PRCMU_BASE + reg);
+       val = ((val & ~mask) | (value & mask));
+       writel(val, (_PRCMU_BASE + reg));
+       spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-bool prcmu_has_arm_maxopp(void)
+struct prcmu_fw_version *prcmu_get_fw_version(void)
 {
-       return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
-               PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
+       return fw_info.valid ? &fw_info.version : NULL;
 }
 
-bool prcmu_is_u8400(void)
+bool prcmu_has_arm_maxopp(void)
 {
-       return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0;
+       return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
+               PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
 }
 
 /**
@@ -787,6 +788,124 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
        return 0;
 }
 
+u8 db8500_prcmu_get_power_state_result(void)
+{
+       return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
+}
+
+/* This function decouple the gic from the prcmu */
+int db8500_prcmu_gic_decouple(void)
+{
+       u32 val = readl(PRCM_A9_MASK_REQ);
+
+       /* Set bit 0 register value to 1 */
+       writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ,
+              PRCM_A9_MASK_REQ);
+
+       /* Make sure the register is updated */
+       readl(PRCM_A9_MASK_REQ);
+
+       /* Wait a few cycles for the gic mask completion */
+       udelay(1);
+
+       return 0;
+}
+
+/* This function recouple the gic with the prcmu */
+int db8500_prcmu_gic_recouple(void)
+{
+       u32 val = readl(PRCM_A9_MASK_REQ);
+
+       /* Set bit 0 register value to 0 */
+       writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ);
+
+       return 0;
+}
+
+#define PRCMU_GIC_NUMBER_REGS 5
+
+/*
+ * This function checks if there are pending irq on the gic. It only
+ * makes sense if the gic has been decoupled before with the
+ * db8500_prcmu_gic_decouple function. Disabling an interrupt only
+ * disables the forwarding of the interrupt to any CPU interface. It
+ * does not prevent the interrupt from changing state, for example
+ * becoming pending, or active and pending if it is already
+ * active. Hence, we have to check the interrupt is pending *and* is
+ * active.
+ */
+bool db8500_prcmu_gic_pending_irq(void)
+{
+       u32 pr; /* Pending register */
+       u32 er; /* Enable register */
+       void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
+       int i;
+
+        /* 5 registers. STI & PPI not skipped */
+       for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
+
+               pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
+               er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+               if (pr & er)
+                       return true; /* There is a pending interrupt */
+       }
+
+       return false;
+}
+
+/*
+ * This function checks if there are pending interrupt on the
+ * prcmu which has been delegated to monitor the irqs with the
+ * db8500_prcmu_copy_gic_settings function.
+ */
+bool db8500_prcmu_pending_irq(void)
+{
+       u32 it, im;
+       int i;
+
+       for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
+               it = readl(PRCM_ARMITVAL31TO0 + i * 4);
+               im = readl(PRCM_ARMITMSK31TO0 + i * 4);
+               if (it & im)
+                       return true; /* There is a pending interrupt */
+       }
+
+       return false;
+}
+
+/*
+ * This function checks if the specified cpu is in in WFI. It's usage
+ * makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple
+ * function. Of course passing smp_processor_id() to this function will
+ * always return false...
+ */
+bool db8500_prcmu_is_cpu_in_wfi(int cpu)
+{
+       return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
+                    PRCM_ARM_WFI_STANDBY_WFI0;
+}
+
+/*
+ * This function copies the gic SPI settings to the prcmu in order to
+ * monitor them and abort/finish the retention/off sequence or state.
+ */
+int db8500_prcmu_copy_gic_settings(void)
+{
+       u32 er; /* Enable register */
+       void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
+       int i;
+
+        /* We skip the STI and PPI */
+       for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
+               er = readl_relaxed(dist_base +
+                                  GIC_DIST_ENABLE_SET + (i + 1) * 4);
+               writel(er, PRCM_ARMITMSK31TO0 + i * 4);
+       }
+
+       return 0;
+}
+
 /* This function should only be called while mb0_transfer.lock is held. */
 static void config_wakeups(void)
 {
@@ -909,23 +1028,23 @@ int db8500_prcmu_get_arm_opp(void)
 }
 
 /**
- * prcmu_get_ddr_opp - get the current DDR OPP
+ * db8500_prcmu_get_ddr_opp - get the current DDR OPP
  *
  * Returns: the current DDR OPP
  */
-int prcmu_get_ddr_opp(void)
+int db8500_prcmu_get_ddr_opp(void)
 {
        return readb(PRCM_DDR_SUBSYS_APE_MINBW);
 }
 
 /**
- * set_ddr_opp - set the appropriate DDR OPP
+ * db8500_set_ddr_opp - set the appropriate DDR OPP
  * @opp: The new DDR operating point to which transition is to be made
  * Returns: 0 on success, non-zero on failure
  *
  * This function sets the operating point of the DDR.
  */
-int prcmu_set_ddr_opp(u8 opp)
+int db8500_prcmu_set_ddr_opp(u8 opp)
 {
        if (opp < DDR_100_OPP || opp > DDR_25_OPP)
                return -EINVAL;
@@ -935,25 +1054,82 @@ int prcmu_set_ddr_opp(u8 opp)
 
        return 0;
 }
+
+/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */
+static void request_even_slower_clocks(bool enable)
+{
+       void __iomem *clock_reg[] = {
+               PRCM_ACLK_MGT,
+               PRCM_DMACLK_MGT
+       };
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&clk_mgt_lock, flags);
+
+       /* Grab the HW semaphore. */
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+               cpu_relax();
+
+       for (i = 0; i < ARRAY_SIZE(clock_reg); i++) {
+               u32 val;
+               u32 div;
+
+               val = readl(clock_reg[i]);
+               div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK);
+               if (enable) {
+                       if ((div <= 1) || (div > 15)) {
+                               pr_err("prcmu: Bad clock divider %d in %s\n",
+                                       div, __func__);
+                               goto unlock_and_return;
+                       }
+                       div <<= 1;
+               } else {
+                       if (div <= 2)
+                               goto unlock_and_return;
+                       div >>= 1;
+               }
+               val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) |
+                       (div & PRCM_CLK_MGT_CLKPLLDIV_MASK));
+               writel(val, clock_reg[i]);
+       }
+
+unlock_and_return:
+       /* Release the HW semaphore. */
+       writel(0, PRCM_SEM);
+
+       spin_unlock_irqrestore(&clk_mgt_lock, flags);
+}
+
 /**
- * set_ape_opp - set the appropriate APE OPP
+ * db8500_set_ape_opp - set the appropriate APE OPP
  * @opp: The new APE operating point to which transition is to be made
  * Returns: 0 on success, non-zero on failure
  *
  * This function sets the operating point of the APE.
  */
-int prcmu_set_ape_opp(u8 opp)
+int db8500_prcmu_set_ape_opp(u8 opp)
 {
        int r = 0;
 
+       if (opp == mb1_transfer.ape_opp)
+               return 0;
+
        mutex_lock(&mb1_transfer.lock);
 
+       if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)
+               request_even_slower_clocks(false);
+
+       if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP))
+               goto skip_message;
+
        while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
        writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
-       writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
+       writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp),
+               (tcdm_base + PRCM_REQ_MB1_APE_OPP));
 
        writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
@@ -962,17 +1138,24 @@ int prcmu_set_ape_opp(u8 opp)
                (mb1_transfer.ack.ape_opp != opp))
                r = -EIO;
 
+skip_message:
+       if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
+               (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)))
+               request_even_slower_clocks(true);
+       if (!r)
+               mb1_transfer.ape_opp = opp;
+
        mutex_unlock(&mb1_transfer.lock);
 
        return r;
 }
 
 /**
- * prcmu_get_ape_opp - get the current APE OPP
+ * db8500_prcmu_get_ape_opp - get the current APE OPP
  *
  * Returns: the current APE OPP
  */
-int prcmu_get_ape_opp(void)
+int db8500_prcmu_get_ape_opp(void)
 {
        return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
 }
@@ -1056,7 +1239,9 @@ static int request_pll(u8 clock, bool enable)
 {
        int r = 0;
 
-       if (clock == PRCMU_PLLSOC1)
+       if (clock == PRCMU_PLLSOC0)
+               clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF);
+       else if (clock == PRCMU_PLLSOC1)
                clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
        else
                return -EINVAL;
@@ -1080,132 +1265,6 @@ static int request_pll(u8 clock, bool enable)
        return r;
 }
 
-/**
- * prcmu_set_hwacc - set the power state of a h/w accelerator
- * @hwacc_dev: The hardware accelerator (enum hw_acc_dev).
- * @state: The new power state (enum hw_acc_state).
- *
- * This function sets the power state of a hardware accelerator.
- * This function should not be called from interrupt context.
- *
- * NOTE! Deprecated, to be removed when all users switched over to use the
- * regulator framework API.
- */
-int prcmu_set_hwacc(u16 hwacc_dev, u8 state)
-{
-       int r = 0;
-       bool ram_retention = false;
-       bool enable, enable_ret;
-
-       /* check argument */
-       BUG_ON(hwacc_dev >= NUM_HW_ACC);
-
-       /* get state of switches */
-       enable = hwacc_enabled[hwacc_dev];
-       enable_ret = hwacc_ret_enabled[hwacc_dev];
-
-       /* set flag if retention is possible */
-       switch (hwacc_dev) {
-       case HW_ACC_SVAMMDSP:
-       case HW_ACC_SIAMMDSP:
-       case HW_ACC_ESRAM1:
-       case HW_ACC_ESRAM2:
-       case HW_ACC_ESRAM3:
-       case HW_ACC_ESRAM4:
-               ram_retention = true;
-               break;
-       }
-
-       /* check argument */
-       BUG_ON(state > HW_ON);
-       BUG_ON(state == HW_OFF_RAMRET && !ram_retention);
-
-       /* modify enable flags */
-       switch (state) {
-       case HW_OFF:
-               enable_ret = false;
-               enable = false;
-               break;
-       case HW_ON:
-               enable = true;
-               break;
-       case HW_OFF_RAMRET:
-               enable_ret = true;
-               enable = false;
-               break;
-       }
-
-       /* get regulator (lazy) */
-       if (hwacc_regulator[hwacc_dev] == NULL) {
-               hwacc_regulator[hwacc_dev] = regulator_get(NULL,
-                       hwacc_regulator_name[hwacc_dev]);
-               if (IS_ERR(hwacc_regulator[hwacc_dev])) {
-                       pr_err("prcmu: failed to get supply %s\n",
-                               hwacc_regulator_name[hwacc_dev]);
-                       r = PTR_ERR(hwacc_regulator[hwacc_dev]);
-                       goto out;
-               }
-       }
-
-       if (ram_retention) {
-               if (hwacc_ret_regulator[hwacc_dev] == NULL) {
-                       hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL,
-                               hwacc_ret_regulator_name[hwacc_dev]);
-                       if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) {
-                               pr_err("prcmu: failed to get supply %s\n",
-                                       hwacc_ret_regulator_name[hwacc_dev]);
-                               r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]);
-                               goto out;
-                       }
-               }
-       }
-
-       /* set regulators */
-       if (ram_retention) {
-               if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) {
-                       r = regulator_enable(hwacc_ret_regulator[hwacc_dev]);
-                       if (r < 0) {
-                               pr_err("prcmu_set_hwacc: ret enable failed\n");
-                               goto out;
-                       }
-                       hwacc_ret_enabled[hwacc_dev] = true;
-               }
-       }
-
-       if (enable && !hwacc_enabled[hwacc_dev]) {
-               r = regulator_enable(hwacc_regulator[hwacc_dev]);
-               if (r < 0) {
-                       pr_err("prcmu_set_hwacc: enable failed\n");
-                       goto out;
-               }
-               hwacc_enabled[hwacc_dev] = true;
-       }
-
-       if (!enable && hwacc_enabled[hwacc_dev]) {
-               r = regulator_disable(hwacc_regulator[hwacc_dev]);
-               if (r < 0) {
-                       pr_err("prcmu_set_hwacc: disable failed\n");
-                       goto out;
-               }
-               hwacc_enabled[hwacc_dev] = false;
-       }
-
-       if (ram_retention) {
-               if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) {
-                       r = regulator_disable(hwacc_ret_regulator[hwacc_dev]);
-                       if (r < 0) {
-                               pr_err("prcmu_set_hwacc: ret disable failed\n");
-                               goto out;
-                       }
-                       hwacc_ret_enabled[hwacc_dev] = false;
-               }
-       }
-
-out:
-       return r;
-}
-EXPORT_SYMBOL(prcmu_set_hwacc);
-
 /**
  * db8500_prcmu_set_epod - set the state of a EPOD (power domain)
  * @epod_id: The EPOD to set
@@ -1375,7 +1434,7 @@ static int request_timclk(bool enable)
        return 0;
 }
 
-static int request_reg_clock(u8 clock, bool enable)
+static int request_clock(u8 clock, bool enable)
 {
        u32 val;
        unsigned long flags;
@@ -1386,14 +1445,14 @@ static int request_reg_clock(u8 clock, bool enable)
        while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
-       val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
+       val = readl(clk_mgt[clock].reg);
        if (enable) {
                val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
        } else {
                clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
                val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
        }
-       writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
+       writel(val, clk_mgt[clock].reg);
 
        /* Release the HW semaphore. */
        writel(0, PRCM_SEM);
@@ -1413,7 +1472,7 @@ static int request_sga_clock(u8 clock, bool enable)
                writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
        }
 
-       ret = request_reg_clock(clock, enable);
+       ret = request_clock(clock, enable);
 
        if (!ret && !enable) {
                val = readl(PRCM_CGATING_BYPASS);
@@ -1423,6 +1482,78 @@ static int request_sga_clock(u8 clock, bool enable)
        return ret;
 }
 
+static inline bool plldsi_locked(void)
+{
+       return (readl(PRCM_PLLDSI_LOCKP) &
+               (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+                PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) ==
+               (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+                PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3);
+}
+
+static int request_plldsi(bool enable)
+{
+       int r = 0;
+       u32 val;
+
+       writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+               PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ?
+               PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET));
+
+       val = readl(PRCM_PLLDSI_ENABLE);
+       if (enable)
+               val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+       else
+               val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+       writel(val, PRCM_PLLDSI_ENABLE);
+
+       if (enable) {
+               unsigned int i;
+               bool locked = plldsi_locked();
+
+               for (i = 10; !locked && (i > 0); --i) {
+                       udelay(100);
+                       locked = plldsi_locked();
+               }
+               if (locked) {
+                       writel(PRCM_APE_RESETN_DSIPLL_RESETN,
+                               PRCM_APE_RESETN_SET);
+               } else {
+                       writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+                               PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
+                               PRCM_MMIP_LS_CLAMP_SET);
+                       val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+                       writel(val, PRCM_PLLDSI_ENABLE);
+                       r = -EAGAIN;
+               }
+       } else {
+               writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR);
+       }
+       return r;
+}
+
+static int request_dsiclk(u8 n, bool enable)
+{
+       u32 val;
+
+       val = readl(PRCM_DSI_PLLOUT_SEL);
+       val &= ~dsiclk[n].divsel_mask;
+       val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) <<
+               dsiclk[n].divsel_shift);
+       writel(val, PRCM_DSI_PLLOUT_SEL);
+       return 0;
+}
+
+static int request_dsiescclk(u8 n, bool enable)
+{
+       u32 val;
+
+       val = readl(PRCM_DSITVCLK_DIV);
+       enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en);
+       writel(val, PRCM_DSITVCLK_DIV);
+       return 0;
+}
+
 /**
  * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
  * @clock:      The clock for which the request is made.
@@ -1433,21 +1564,435 @@ static int request_sga_clock(u8 clock, bool enable)
  */
 int db8500_prcmu_request_clock(u8 clock, bool enable)
 {
-       switch(clock) {
-       case PRCMU_SGACLK:
+       if (clock == PRCMU_SGACLK)
                return request_sga_clock(clock, enable);
-       case PRCMU_TIMCLK:
+       else if (clock < PRCMU_NUM_REG_CLOCKS)
+               return request_clock(clock, enable);
+       else if (clock == PRCMU_TIMCLK)
                return request_timclk(enable);
-       case PRCMU_SYSCLK:
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               return request_dsiclk((clock - PRCMU_DSI0CLK), enable);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable);
+       else if (clock == PRCMU_PLLDSI)
+               return request_plldsi(enable);
+       else if (clock == PRCMU_SYSCLK)
                return request_sysclk(enable);
-       case PRCMU_PLLSOC1:
+       else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1))
                return request_pll(clock, enable);
+       else
+               return -EINVAL;
+}
+
+static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
+       int branch)
+{
+       u64 rate;
+       u32 val;
+       u32 d;
+       u32 div = 1;
+
+       val = readl(reg);
+
+       rate = src_rate;
+       rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT);
+
+       d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT);
+       if (d > 1)
+               div *= d;
+
+       d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT);
+       if (d > 1)
+               div *= d;
+
+       if (val & PRCM_PLL_FREQ_SELDIV2)
+               div *= 2;
+
+       if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
+               (val & PRCM_PLL_FREQ_DIV2EN) &&
+               ((reg == PRCM_PLLSOC0_FREQ) ||
+                (reg == PRCM_PLLDDR_FREQ))))
+               div *= 2;
+
+       (void)do_div(rate, div);
+
+       return (unsigned long)rate;
+}
+
+#define ROOT_CLOCK_RATE 38400000
+
+static unsigned long clock_rate(u8 clock)
+{
+       u32 val;
+       u32 pllsw;
+       unsigned long rate = ROOT_CLOCK_RATE;
+
+       val = readl(clk_mgt[clock].reg);
+
+       if (val & PRCM_CLK_MGT_CLK38) {
+               if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV))
+                       rate /= 2;
+               return rate;
+       }
+
+       val |= clk_mgt[clock].pllsw;
+       pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
+
+       if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0)
+               rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch);
+       else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1)
+               rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch);
+       else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR)
+               rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch);
+       else
+               return 0;
+
+       if ((clock == PRCMU_SGACLK) &&
+               (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) {
+               u64 r = (rate * 10);
+
+               (void)do_div(r, 25);
+               return (unsigned long)r;
+       }
+       val &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
+       if (val)
+               return rate / val;
+       else
+               return 0;
+}
+
+static unsigned long dsiclk_rate(u8 n)
+{
+       u32 divsel;
+       u32 div = 1;
+
+       divsel = readl(PRCM_DSI_PLLOUT_SEL);
+       divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift);
+
+       if (divsel == PRCM_DSI_PLLOUT_SEL_OFF)
+               divsel = dsiclk[n].divsel;
+
+       switch (divsel) {
+       case PRCM_DSI_PLLOUT_SEL_PHI_4:
+               div *= 2;
+       case PRCM_DSI_PLLOUT_SEL_PHI_2:
+               div *= 2;
+       case PRCM_DSI_PLLOUT_SEL_PHI:
+               return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
+                       PLL_RAW) / div;
        default:
-               break;
+               return 0;
+       }
+}
+
+static unsigned long dsiescclk_rate(u8 n)
+{
+       u32 div;
+
+       div = readl(PRCM_DSITVCLK_DIV);
+       div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift));
+       return clock_rate(PRCMU_TVCLK) / max((u32)1, div);
+}
+
+unsigned long prcmu_clock_rate(u8 clock)
+{
+       if (clock < PRCMU_NUM_REG_CLOCKS)
+               return clock_rate(clock);
+       else if (clock == PRCMU_TIMCLK)
+               return ROOT_CLOCK_RATE / 16;
+       else if (clock == PRCMU_SYSCLK)
+               return ROOT_CLOCK_RATE;
+       else if (clock == PRCMU_PLLSOC0)
+               return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+       else if (clock == PRCMU_PLLSOC1)
+               return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+       else if (clock == PRCMU_PLLDDR)
+               return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+       else if (clock == PRCMU_PLLDSI)
+               return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
+                       PLL_RAW);
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               return dsiclk_rate(clock - PRCMU_DSI0CLK);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
+       else
+               return 0;
+}
+
+static unsigned long clock_source_rate(u32 clk_mgt_val, int branch)
+{
+       if (clk_mgt_val & PRCM_CLK_MGT_CLK38)
+               return ROOT_CLOCK_RATE;
+       clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK;
+       if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0)
+               return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch);
+       else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1)
+               return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch);
+       else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR)
+               return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch);
+       else
+               return 0;
+}
+
+static u32 clock_divider(unsigned long src_rate, unsigned long rate)
+{
+       u32 div;
+
+       div = (src_rate / rate);
+       if (div == 0)
+               return 1;
+       if (rate < (src_rate / div))
+               div++;
+       return div;
+}
+
+static long round_clock_rate(u8 clock, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+       unsigned long src_rate;
+       long rounded_rate;
+
+       val = readl(clk_mgt[clock].reg);
+       src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
+               clk_mgt[clock].branch);
+       div = clock_divider(src_rate, rate);
+       if (val & PRCM_CLK_MGT_CLK38) {
+               if (clk_mgt[clock].clk38div) {
+                       if (div > 2)
+                               div = 2;
+               } else {
+                       div = 1;
+               }
+       } else if ((clock == PRCMU_SGACLK) && (div == 3)) {
+               u64 r = (src_rate * 10);
+
+               (void)do_div(r, 25);
+               if (r <= rate)
+                       return (unsigned long)r;
+       }
+       rounded_rate = (src_rate / min(div, (u32)31));
+
+       return rounded_rate;
+}
+
+#define MIN_PLL_VCO_RATE 600000000ULL
+#define MAX_PLL_VCO_RATE 1680640000ULL
+
+static long round_plldsi_rate(unsigned long rate)
+{
+       long rounded_rate = 0;
+       unsigned long src_rate;
+       unsigned long rem;
+       u32 r;
+
+       src_rate = clock_rate(PRCMU_HDMICLK);
+       rem = rate;
+
+       for (r = 7; (rem > 0) && (r > 0); r--) {
+               u64 d;
+
+               d = (r * rate);
+               (void)do_div(d, src_rate);
+               if (d < 6)
+                       d = 6;
+               else if (d > 255)
+                       d = 255;
+               d *= src_rate;
+               if (((2 * d) < (r * MIN_PLL_VCO_RATE)) ||
+                       ((r * MAX_PLL_VCO_RATE) < (2 * d)))
+                       continue;
+               (void)do_div(d, r);
+               if (rate < d) {
+                       if (rounded_rate == 0)
+                               rounded_rate = (long)d;
+                       break;
+               }
+               if ((rate - d) < rem) {
+                       rem = (rate - d);
+                       rounded_rate = (long)d;
+               }
+       }
+       return rounded_rate;
+}
+
+static long round_dsiclk_rate(unsigned long rate)
+{
+       u32 div;
+       unsigned long src_rate;
+       long rounded_rate;
+
+       src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
+               PLL_RAW);
+       div = clock_divider(src_rate, rate);
+       rounded_rate = (src_rate / ((div > 2) ? 4 : div));
+
+       return rounded_rate;
+}
+
+static long round_dsiescclk_rate(unsigned long rate)
+{
+       u32 div;
+       unsigned long src_rate;
+       long rounded_rate;
+
+       src_rate = clock_rate(PRCMU_TVCLK);
+       div = clock_divider(src_rate, rate);
+       rounded_rate = (src_rate / min(div, (u32)255));
+
+       return rounded_rate;
+}
+
+long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+       if (clock < PRCMU_NUM_REG_CLOCKS)
+               return round_clock_rate(clock, rate);
+       else if (clock == PRCMU_PLLDSI)
+               return round_plldsi_rate(rate);
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               return round_dsiclk_rate(rate);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               return round_dsiescclk_rate(rate);
+       else
+               return (long)prcmu_clock_rate(clock);
+}
+
+static void set_clock_rate(u8 clock, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+       unsigned long src_rate;
+       unsigned long flags;
+
+       spin_lock_irqsave(&clk_mgt_lock, flags);
+
+       /* Grab the HW semaphore. */
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+               cpu_relax();
+
+       val = readl(clk_mgt[clock].reg);
+       src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
+               clk_mgt[clock].branch);
+       div = clock_divider(src_rate, rate);
+       if (val & PRCM_CLK_MGT_CLK38) {
+               if (clk_mgt[clock].clk38div) {
+                       if (div > 1)
+                               val |= PRCM_CLK_MGT_CLK38DIV;
+                       else
+                               val &= ~PRCM_CLK_MGT_CLK38DIV;
+               }
+       } else if (clock == PRCMU_SGACLK) {
+               val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK |
+                       PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN);
+               if (div == 3) {
+                       u64 r = (src_rate * 10);
+
+                       (void)do_div(r, 25);
+                       if (r <= rate) {
+                               val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN;
+                               div = 0;
+                       }
+               }
+               val |= min(div, (u32)31);
+       } else {
+               val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK;
+               val |= min(div, (u32)31);
+       }
+       writel(val, clk_mgt[clock].reg);
+
+       /* Release the HW semaphore. */
+       writel(0, PRCM_SEM);
+
+       spin_unlock_irqrestore(&clk_mgt_lock, flags);
+}
+
+static int set_plldsi_rate(unsigned long rate)
+{
+       unsigned long src_rate;
+       unsigned long rem;
+       u32 pll_freq = 0;
+       u32 r;
+
+       src_rate = clock_rate(PRCMU_HDMICLK);
+       rem = rate;
+
+       for (r = 7; (rem > 0) && (r > 0); r--) {
+               u64 d;
+               u64 hwrate;
+
+               d = (r * rate);
+               (void)do_div(d, src_rate);
+               if (d < 6)
+                       d = 6;
+               else if (d > 255)
+                       d = 255;
+               hwrate = (d * src_rate);
+               if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) ||
+                       ((r * MAX_PLL_VCO_RATE) < (2 * hwrate)))
+                       continue;
+               (void)do_div(hwrate, r);
+               if (rate < hwrate) {
+                       if (pll_freq == 0)
+                               pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
+                                       (r << PRCM_PLL_FREQ_R_SHIFT));
+                       break;
+               }
+               if ((rate - hwrate) < rem) {
+                       rem = (rate - hwrate);
+                       pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
+                               (r << PRCM_PLL_FREQ_R_SHIFT));
+               }
        }
+       if (pll_freq == 0)
+               return -EINVAL;
+
+       pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT);
+       writel(pll_freq, PRCM_PLLDSI_FREQ);
+
+       return 0;
+}
+
+static void set_dsiclk_rate(u8 n, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+
+       div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ,
+                       clock_rate(PRCMU_HDMICLK), PLL_RAW), rate);
+
+       dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI :
+                          (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 :
+                          /* else */   PRCM_DSI_PLLOUT_SEL_PHI_4;
+
+       val = readl(PRCM_DSI_PLLOUT_SEL);
+       val &= ~dsiclk[n].divsel_mask;
+       val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift);
+       writel(val, PRCM_DSI_PLLOUT_SEL);
+}
+
+static void set_dsiescclk_rate(u8 n, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+
+       div = clock_divider(clock_rate(PRCMU_TVCLK), rate);
+       val = readl(PRCM_DSITVCLK_DIV);
+       val &= ~dsiescclk[n].div_mask;
+       val |= (min(div, (u32)255) << dsiescclk[n].div_shift);
+       writel(val, PRCM_DSITVCLK_DIV);
+}
+
+int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
        if (clock < PRCMU_NUM_REG_CLOCKS)
-               return request_reg_clock(clock, enable);
-       return -EINVAL;
+               set_clock_rate(clock, rate);
+       else if (clock == PRCMU_PLLDSI)
+               return set_plldsi_rate(rate);
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate);
+       return 0;
 }
 
 int db8500_prcmu_config_esram0_deep_sleep(u8 state)
@@ -1476,7 +2021,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state)
        return 0;
 }
 
-int prcmu_config_hotdog(u8 threshold)
+int db8500_prcmu_config_hotdog(u8 threshold)
 {
        mutex_lock(&mb4_transfer.lock);
 
@@ -1494,7 +2039,7 @@ int prcmu_config_hotdog(u8 threshold)
        return 0;
 }
 
-int prcmu_config_hotmon(u8 low, u8 high)
+int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
        mutex_lock(&mb4_transfer.lock);
 
@@ -1533,7 +2078,7 @@ static int config_hot_period(u16 val)
        return 0;
 }
 
-int prcmu_start_temp_sense(u16 cycles32k)
+int db8500_prcmu_start_temp_sense(u16 cycles32k)
 {
        if (cycles32k == 0xFFFF)
                return -EINVAL;
@@ -1541,7 +2086,7 @@ int prcmu_start_temp_sense(u16 cycles32k)
        return config_hot_period(cycles32k);
 }
 
-int prcmu_stop_temp_sense(void)
+int db8500_prcmu_stop_temp_sense(void)
 {
        return config_hot_period(0xFFFF);
 }
@@ -1570,7 +2115,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 
 }
 
-int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 {
        BUG_ON(num == 0 || num > 0xf);
        return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0,
@@ -1578,17 +2123,17 @@ int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
                            A9WDOG_AUTO_OFF_DIS);
 }
 
-int prcmu_enable_a9wdog(u8 id)
+int db8500_prcmu_enable_a9wdog(u8 id)
 {
        return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
 }
 
-int prcmu_disable_a9wdog(u8 id)
+int db8500_prcmu_disable_a9wdog(u8 id)
 {
        return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
 }
 
-int prcmu_kick_a9wdog(u8 id)
+int db8500_prcmu_kick_a9wdog(u8 id)
 {
        return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
 }
@@ -1596,16 +2141,8 @@ int prcmu_kick_a9wdog(u8 id)
 /*
  * timeout is 28 bit, in ms.
  */
-#define MAX_WATCHDOG_TIMEOUT 131000
-int prcmu_load_a9wdog(u8 id, u32 timeout)
+int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
 {
-       if (timeout > MAX_WATCHDOG_TIMEOUT)
-               /*
-                * Due to calculation bug in prcmu fw, timeouts
-                * can't be bigger than 131 seconds.
-                */
-               return -EINVAL;
-
        return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
                            (id & A9WDOG_ID_MASK) |
                            /*
@@ -1618,41 +2155,6 @@ int prcmu_load_a9wdog(u8 id, u32 timeout)
                            (u8)((timeout >> 20) & 0xff));
 }
 
-/**
- * prcmu_set_clock_divider() - Configure the clock divider.
- * @clock:     The clock for which the request is made.
- * @divider:   The clock divider. (< 32)
- *
- * This function should only be used by the clock implementation.
- * Do not use it from any other place!
- */
-int prcmu_set_clock_divider(u8 clock, u8 divider)
-{
-       u32 val;
-       unsigned long flags;
-
-       if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider))
-               return -EINVAL;
-
-       spin_lock_irqsave(&clk_mgt_lock, flags);
-
-       /* Grab the HW semaphore. */
-       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
-               cpu_relax();
-
-       val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
-       val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK);
-       val |= (u32)divider;
-       writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
-
-       /* Release the HW semaphore. */
-       writel(0, PRCM_SEM);
-
-       spin_unlock_irqrestore(&clk_mgt_lock, flags);
-
-       return 0;
-}
-
 /**
  * prcmu_abb_read() - Read register value(s) from the ABB.
  * @slave:     The I2C slave address.
@@ -1675,6 +2177,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
        while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
                cpu_relax();
 
+       writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
        writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
        writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
        writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
@@ -1700,16 +2203,19 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 }
 
 /**
- * prcmu_abb_write() - Write register value(s) to the ABB.
+ * prcmu_abb_write_masked() - Write masked register value(s) to the ABB.
  * @slave:     The I2C slave address.
  * @reg:       The (start) register address.
  * @value:     The value(s) to write.
+ * @mask:      The mask(s) to use.
  * @size:      The number of registers to write.
  *
- * Reads register value(s) from the ABB.
+ * Writes masked register value(s) to the ABB.
+ * For each @value, only the bits set to 1 in the corresponding @mask
+ * will be written. The other bits are not changed.
  * @size has to be 1 for the current firmware version.
  */
-int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
 {
        int r;
 
@@ -1721,6 +2227,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
                cpu_relax();
 
+       writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
        writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
        writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
        writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
@@ -1742,6 +2249,23 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        return r;
 }
 
+/**
+ * prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave:     The I2C slave address.
+ * @reg:       The (start) register address.
+ * @value:     The value(s) to write.
+ * @size:      The number of registers to write.
+ *
+ * Writes register value(s) to the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+       u8 mask = ~0;
+
+       return prcmu_abb_write_masked(slave, reg, value, &mask, size);
+}
+
 /**
  * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem
  */
@@ -1850,9 +2374,9 @@ u16 db8500_prcmu_get_reset_code(void)
 }
 
 /**
- * prcmu_reset_modem - ask the PRCMU to reset modem
+ * db8500_prcmu_reset_modem - ask the PRCMU to reset modem
  */
-void prcmu_modem_reset(void)
+void db8500_prcmu_modem_reset(void)
 {
        mutex_lock(&mb1_transfer.lock);
 
@@ -2099,6 +2623,26 @@ static struct irq_chip prcmu_irq_chip = {
        .irq_unmask     = prcmu_irq_unmask,
 };
 
+static char *fw_project_name(u8 project)
+{
+       switch (project) {
+       case PRCMU_FW_PROJECT_U8500:
+               return "U8500";
+       case PRCMU_FW_PROJECT_U8500_C2:
+               return "U8500 C2";
+       case PRCMU_FW_PROJECT_U9500:
+               return "U9500";
+       case PRCMU_FW_PROJECT_U9500_C2:
+               return "U9500 C2";
+       case PRCMU_FW_PROJECT_U8520:
+               return "U8520";
+       case PRCMU_FW_PROJECT_U8420:
+               return "U8420";
+       default:
+               return "Unknown";
+       }
+}
+
 void __init db8500_prcmu_early_init(void)
 {
        unsigned int i;
@@ -2108,11 +2652,13 @@ void __init db8500_prcmu_early_init(void)
                if (tcpm_base != NULL) {
                        u32 version;
                        version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
-                       prcmu_version.project_number = version & 0xFF;
-                       prcmu_version.api_version = (version >> 8) & 0xFF;
-                       prcmu_version.func_version = (version >> 16) & 0xFF;
-                       prcmu_version.errata = (version >> 24) & 0xFF;
-                       pr_info("PRCMU firmware version %d.%d.%d\n",
+                       fw_info.version.project = version & 0xFF;
+                       fw_info.version.api_version = (version >> 8) & 0xFF;
+                       fw_info.version.func_version = (version >> 16) & 0xFF;
+                       fw_info.version.errata = (version >> 24) & 0xFF;
+                       fw_info.valid = true;
+                       pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
+                               fw_project_name(fw_info.version.project),
                                (version >> 8) & 0xFF, (version >> 16) & 0xFF,
                                (version >> 24) & 0xFF);
                        iounmap(tcpm_base);
@@ -2130,6 +2676,7 @@ void __init db8500_prcmu_early_init(void)
        init_completion(&mb0_transfer.ac_wake_work);
        mutex_init(&mb1_transfer.lock);
        init_completion(&mb1_transfer.work);
+       mb1_transfer.ape_opp = APE_NO_CHANGE;
        mutex_init(&mb2_transfer.lock);
        init_completion(&mb2_transfer.work);
        spin_lock_init(&mb2_transfer.auto_pm_lock);
@@ -2154,7 +2701,7 @@ void __init db8500_prcmu_early_init(void)
        }
 }
 
-static void __init db8500_prcmu_init_clkforce(void)
+static void __init init_prcm_registers(void)
 {
        u32 val;
 
@@ -2186,19 +2733,17 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = {
        REGULATOR_SUPPLY("vcore", "uart1"),
        REGULATOR_SUPPLY("vcore", "uart2"),
        REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"),
+       REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"),
 };
 
 static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
-       /* CG2900 and CW1200 power to off-chip peripherals */
-       REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"),
-       REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"),
        REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"),
        /* AV8100 regulator */
        REGULATOR_SUPPLY("hdmi_1v8", "0-0070"),
 };
 
 static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
-       REGULATOR_SUPPLY("vsupply", "b2r2.0"),
+       REGULATOR_SUPPLY("vsupply", "b2r2_bus"),
        REGULATOR_SUPPLY("vsupply", "mcde"),
 };
 
@@ -2235,6 +2780,7 @@ static struct regulator_consumer_supply db8500_esram12_consumers[] = {
 static struct regulator_consumer_supply db8500_esram34_consumers[] = {
        REGULATOR_SUPPLY("v-esram34", "mcde"),
        REGULATOR_SUPPLY("esram34", "cm_control"),
+       REGULATOR_SUPPLY("lcla_esram", "dma40.0"),
 };
 
 static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
@@ -2291,7 +2837,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sva-mmdsp",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2307,7 +2853,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sva-pipe",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2316,7 +2862,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
        },
        [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sia-mmdsp",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2331,7 +2877,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sia-pipe",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2359,7 +2905,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers),
        },
        [DB8500_REGULATOR_SWITCH_ESRAM12] = {
-               .supply_regulator = "db8500-vape",
+               /*
+                * esram12 is set in retention and supplied by Vsafe when Vape is off,
+                * no need to hold Vape
+                */
                .constraints = {
                        .name = "db8500-esram12",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2374,7 +2923,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_ESRAM34] = {
-               .supply_regulator = "db8500-vape",
+               /*
+                * esram34 is set in retention and supplied by Vsafe when Vape is off,
+                * no need to hold Vape
+                */
                .constraints = {
                        .name = "db8500-esram34",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2412,7 +2964,7 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev)
        if (ux500_is_svp())
                return -ENODEV;
 
-       db8500_prcmu_init_clkforce();
+       init_prcm_registers();
 
        /* Clean up the mailbox interrupts after pre-kernel code. */
        writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
index ec22e9f15d32eefad28f44e3dd7fa1c31b4277f6..3a0bf91d7780894a552f0f83d0cd9defb4637c63 100644 (file)
 
 #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
 
-#define PRCM_SVACLK_MGT_OFF            0x008
-#define PRCM_SIACLK_MGT_OFF            0x00C
-#define PRCM_SGACLK_MGT_OFF            0x014
-#define PRCM_UARTCLK_MGT_OFF           0x018
-#define PRCM_MSP02CLK_MGT_OFF          0x01C
-#define PRCM_I2CCLK_MGT_OFF            0x020
-#define PRCM_SDMMCCLK_MGT_OFF          0x024
-#define PRCM_SLIMCLK_MGT_OFF           0x028
-#define PRCM_PER1CLK_MGT_OFF           0x02C
-#define PRCM_PER2CLK_MGT_OFF           0x030
-#define PRCM_PER3CLK_MGT_OFF           0x034
-#define PRCM_PER5CLK_MGT_OFF           0x038
-#define PRCM_PER6CLK_MGT_OFF           0x03C
-#define PRCM_PER7CLK_MGT_OFF           0x040
-#define PRCM_PWMCLK_MGT_OFF            0x044 /* for DB5500 */
-#define PRCM_IRDACLK_MGT_OFF           0x048 /* for DB5500 */
-#define PRCM_IRRCCLK_MGT_OFF           0x04C /* for DB5500 */
-#define PRCM_LCDCLK_MGT_OFF            0x044
-#define PRCM_BMLCLK_MGT_OFF            0x04C
-#define PRCM_HSITXCLK_MGT_OFF          0x050
-#define PRCM_HSIRXCLK_MGT_OFF          0x054
-#define PRCM_HDMICLK_MGT_OFF           0x058
-#define PRCM_APEATCLK_MGT_OFF          0x05C
-#define PRCM_APETRACECLK_MGT_OFF       0x060
-#define PRCM_MCDECLK_MGT_OFF           0x064
-#define PRCM_IPI2CCLK_MGT_OFF          0x068
-#define PRCM_DSIALTCLK_MGT_OFF         0x06C
-#define PRCM_DMACLK_MGT_OFF            0x074
-#define PRCM_B2R2CLK_MGT_OFF           0x078
-#define PRCM_TVCLK_MGT_OFF             0x07C
-#define PRCM_UNIPROCLK_MGT_OFF         0x278
-#define PRCM_SSPCLK_MGT_OFF            0x280
-#define PRCM_RNGCLK_MGT_OFF            0x284
-#define PRCM_UICCCLK_MGT_OFF           0x27C
-#define PRCM_MSP1CLK_MGT_OFF           0x288
+#define PRCM_CLK_MGT(_offset) (void __iomem *)(IO_ADDRESS(U8500_PRCMU_BASE) \
+       + _offset)
+#define PRCM_ACLK_MGT          PRCM_CLK_MGT(0x004)
+#define PRCM_SVACLK_MGT                PRCM_CLK_MGT(0x008)
+#define PRCM_SIACLK_MGT                PRCM_CLK_MGT(0x00C)
+#define PRCM_SGACLK_MGT                PRCM_CLK_MGT(0x014)
+#define PRCM_UARTCLK_MGT       PRCM_CLK_MGT(0x018)
+#define PRCM_MSP02CLK_MGT      PRCM_CLK_MGT(0x01C)
+#define PRCM_I2CCLK_MGT                PRCM_CLK_MGT(0x020)
+#define PRCM_SDMMCCLK_MGT      PRCM_CLK_MGT(0x024)
+#define PRCM_SLIMCLK_MGT       PRCM_CLK_MGT(0x028)
+#define PRCM_PER1CLK_MGT       PRCM_CLK_MGT(0x02C)
+#define PRCM_PER2CLK_MGT       PRCM_CLK_MGT(0x030)
+#define PRCM_PER3CLK_MGT       PRCM_CLK_MGT(0x034)
+#define PRCM_PER5CLK_MGT       PRCM_CLK_MGT(0x038)
+#define PRCM_PER6CLK_MGT       PRCM_CLK_MGT(0x03C)
+#define PRCM_PER7CLK_MGT       PRCM_CLK_MGT(0x040)
+#define PRCM_LCDCLK_MGT                PRCM_CLK_MGT(0x044)
+#define PRCM_BMLCLK_MGT                PRCM_CLK_MGT(0x04C)
+#define PRCM_HSITXCLK_MGT      PRCM_CLK_MGT(0x050)
+#define PRCM_HSIRXCLK_MGT      PRCM_CLK_MGT(0x054)
+#define PRCM_HDMICLK_MGT       PRCM_CLK_MGT(0x058)
+#define PRCM_APEATCLK_MGT      PRCM_CLK_MGT(0x05C)
+#define PRCM_APETRACECLK_MGT   PRCM_CLK_MGT(0x060)
+#define PRCM_MCDECLK_MGT       PRCM_CLK_MGT(0x064)
+#define PRCM_IPI2CCLK_MGT      PRCM_CLK_MGT(0x068)
+#define PRCM_DSIALTCLK_MGT     PRCM_CLK_MGT(0x06C)
+#define PRCM_DMACLK_MGT                PRCM_CLK_MGT(0x074)
+#define PRCM_B2R2CLK_MGT       PRCM_CLK_MGT(0x078)
+#define PRCM_TVCLK_MGT         PRCM_CLK_MGT(0x07C)
+#define PRCM_UNIPROCLK_MGT     PRCM_CLK_MGT(0x278)
+#define PRCM_SSPCLK_MGT                PRCM_CLK_MGT(0x280)
+#define PRCM_RNGCLK_MGT                PRCM_CLK_MGT(0x284)
+#define PRCM_UICCCLK_MGT       PRCM_CLK_MGT(0x27C)
+#define PRCM_MSP1CLK_MGT       PRCM_CLK_MGT(0x288)
 
 #define PRCM_ARM_PLLDIVPS      (_PRCMU_BASE + 0x118)
 #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE         0x3f
@@ -79,6 +79,8 @@
 
 /* ARM WFI Standby signal register */
 #define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
+#define PRCM_ARM_WFI_STANDBY_WFI0               0x08
+#define PRCM_ARM_WFI_STANDBY_WFI1               0x10
 #define PRCM_IOCR              (_PRCMU_BASE + 0x310)
 #define PRCM_IOCR_IOFORCE                      0x1
 
 #define PRCM_MMIP_LS_CLAMP_SET     (_PRCMU_BASE + 0x420)
 #define PRCM_MMIP_LS_CLAMP_CLR     (_PRCMU_BASE + 0x424)
 
+#define PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP                BIT(11)
+#define PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI       BIT(22)
+
 /* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLSOC0_FREQ         (_PRCMU_BASE + 0x080)
+#define PRCM_PLLSOC1_FREQ         (_PRCMU_BASE + 0x084)
+#define PRCM_PLLDDR_FREQ          (_PRCMU_BASE + 0x08C)
+#define PRCM_PLL_FREQ_D_SHIFT  0
+#define PRCM_PLL_FREQ_D_MASK   BITS(0, 7)
+#define PRCM_PLL_FREQ_N_SHIFT  8
+#define PRCM_PLL_FREQ_N_MASK   BITS(8, 13)
+#define PRCM_PLL_FREQ_R_SHIFT  16
+#define PRCM_PLL_FREQ_R_MASK   BITS(16, 18)
+#define PRCM_PLL_FREQ_SELDIV2  BIT(24)
+#define PRCM_PLL_FREQ_DIV2EN   BIT(25)
+
 #define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
 #define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
 #define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
-#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF)
-#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF)
-#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF)
-#define PRCM_TVCLK_MGT             (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF)
 #define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
 #define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
 #define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
 #define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
 #define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
 
+#define PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE BIT(0)
+
+#define PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10  BIT(0)
+#define PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3   BIT(1)
+
+#define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT   0
+#define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK    BITS(0, 2)
+#define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT   8
+#define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK    BITS(8, 10)
+
+#define PRCM_DSI_PLLOUT_SEL_OFF                0
+#define PRCM_DSI_PLLOUT_SEL_PHI                1
+#define PRCM_DSI_PLLOUT_SEL_PHI_2      2
+#define PRCM_DSI_PLLOUT_SEL_PHI_4      3
+
+#define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT       0
+#define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK                BITS(0, 7)
+#define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT       8
+#define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK                BITS(8, 15)
+#define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT       16
+#define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK                BITS(16, 23)
+#define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN              BIT(24)
+#define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN              BIT(25)
+#define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN              BIT(26)
+
+#define PRCM_APE_RESETN_DSIPLL_RESETN BIT(14)
+
 #define PRCM_CLKOCR               (_PRCMU_BASE + 0x1CC)
 #define PRCM_CLKOCR_CLKOUT0_REF_CLK    (1 << 0)
 #define PRCM_CLKOCR_CLKOUT0_MASK       BITS(0, 13)
 #define PRCM_CLKOCR_CLKOSEL1_MASK      BITS(22, 24)
 #define PRCM_CLKOCR_CLK1TYPE           BIT(28)
 
-#define PRCM_CLK_MGT_CLKPLLDIV_MASK    BITS(0, 4)
-#define PRCM_CLK_MGT_CLKPLLSW_MASK     BITS(5, 7)
-#define PRCM_CLK_MGT_CLKEN             BIT(8)
+#define PRCM_CLK_MGT_CLKPLLDIV_MASK            BITS(0, 4)
+#define PRCM_CLK_MGT_CLKPLLSW_SOC0             BIT(5)
+#define PRCM_CLK_MGT_CLKPLLSW_SOC1             BIT(6)
+#define PRCM_CLK_MGT_CLKPLLSW_DDR              BIT(7)
+#define PRCM_CLK_MGT_CLKPLLSW_MASK             BITS(5, 7)
+#define PRCM_CLK_MGT_CLKEN                     BIT(8)
+#define PRCM_CLK_MGT_CLK38                     BIT(9)
+#define PRCM_CLK_MGT_CLK38DIV                  BIT(11)
+#define PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN    BIT(12)
 
 /* GPIOCR register */
 #define PRCM_GPIOCR_SPI2_SELECT BIT(23)
index 7122386b4e3cf1830dbb3cab2f552efefeb43834..9fd4f63c45cc18b2e60dc41085425ff3d35f04b8 100644 (file)
@@ -560,6 +560,8 @@ EXPORT_SYMBOL(mc13xxx_get_flags);
 
 #define MC13XXX_ADC1_CHAN0_SHIFT       5
 #define MC13XXX_ADC1_CHAN1_SHIFT       8
+#define MC13783_ADC1_ATO_SHIFT         11
+#define MC13783_ADC1_ATOX              (1 << 19)
 
 struct mc13xxx_adcdone_data {
        struct mc13xxx *mc13xxx;
@@ -580,7 +582,8 @@ static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
 #define MC13XXX_ADC_WORKING (1 << 0)
 
 int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
-               unsigned int channel, unsigned int *sample)
+               unsigned int channel, u8 ato, bool atox,
+               unsigned int *sample)
 {
        u32 adc0, adc1, old_adc0;
        int i, ret;
@@ -631,6 +634,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
                return -EINVAL;
        }
 
+       adc1 |= ato << MC13783_ADC1_ATO_SHIFT;
+       if (atox)
+               adc1 |= MC13783_ADC1_ATOX;
        dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__);
        mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
                        mc13xxx_handler_adcdone, __func__, &adcdone_data);
@@ -813,7 +819,8 @@ err_revision:
                mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
 
        if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
-               mc13xxx_add_subdevice(mc13xxx, "%s-ts");
+               mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts",
+                               &pdata->touch, sizeof(pdata->touch));
 
        if (pdata) {
                mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
index 6acf2e03f2baa935039690637ff8b3c0f793ff2b..62e5e3617eb0e34b2bc0bb8985b31da5f39aa2d7 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/string.h>
 #include <linux/mfd/mcp.h>
 
-#include <asm/system.h>
-
 
 #define to_mcp(d)              container_of(d, struct mcp, attached_device)
 #define to_mcp_driver(d)       container_of(d, struct mcp_driver, drv)
index 1c0ceacaa1f6463db20cf2a275df68747c9cf80f..c54e244ca0cfa28b40a6182c65e6f8f3d81c1da6 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <mach/mcp.h>
 
 #define DRIVER_NAME "sa11x0-mcp"
index 411f523d4878bd1cec6f8783ca6c99d6b57b669e..ffc3d48676ae67c5c838700d212310025ec8f2da 100644 (file)
@@ -162,7 +162,7 @@ int mfd_add_devices(struct device *parent, int id,
        atomic_t *cnts;
 
        /* initialize reference counting for all cells */
-       cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL);
+       cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL);
        if (!cnts)
                return -ENOMEM;
 
index 68ac2c55d5ae0bb1381c0681b641846079345f54..95a2e546a48962c18cfaa151aa7dc539e4c94035 100644 (file)
@@ -170,7 +170,7 @@ struct usbhs_hcd_omap {
 /*-------------------------------------------------------------------------*/
 
 const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
-static u64 usbhs_dmamask = ~(u32)0;
+static u64 usbhs_dmamask = DMA_BIT_MASK(32);
 
 /*-------------------------------------------------------------------------*/
 
@@ -223,7 +223,7 @@ static struct platform_device *omap_usbhs_alloc_child(const char *name,
        }
 
        child->dev.dma_mask             = &usbhs_dmamask;
-       child->dev.coherent_dma_mask    = 0xffffffff;
+       dma_set_coherent_mask(&child->dev, DMA_BIT_MASK(32));
        child->dev.parent               = dev;
 
        ret = platform_device_add(child);
@@ -799,14 +799,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, omap);
 
+       omap_usbhs_init(dev);
        ret = omap_usbhs_alloc_children(pdev);
        if (ret) {
                dev_err(dev, "omap_usbhs_alloc_children failed\n");
                goto err_alloc;
        }
 
-       omap_usbhs_init(dev);
-
        goto end_probe;
 
 err_alloc:
index ff1a7e741ecdfc6d8eb3d27cacaa47a1b492768a..189c2f07b83f4331af92528886864e0f5c5fa1d7 100644 (file)
@@ -46,13 +46,7 @@ EXPORT_SYMBOL_GPL(pcf50633_read_block);
 int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
                                        int nr_regs, u8 *data)
 {
-       int ret;
-
-       ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs);
-       if (ret != 0)
-               return ret;
-
-       return nr_regs;
+       return regmap_raw_write(pcf->regmap, reg, data, nr_regs);
 }
 EXPORT_SYMBOL_GPL(pcf50633_write_block);
 
index 9ab19a8f669dfa5a5b2fef8942aff5e90df3d073..d02ddf2ebd630ab7b2e77267c0290bc6742d4f58 100644 (file)
 
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/gpio.h>
-
-enum pcf50633_regulator_id {
-       PCF50633_REGULATOR_AUTO,
-       PCF50633_REGULATOR_DOWN1,
-       PCF50633_REGULATOR_DOWN2,
-       PCF50633_REGULATOR_LDO1,
-       PCF50633_REGULATOR_LDO2,
-       PCF50633_REGULATOR_LDO3,
-       PCF50633_REGULATOR_LDO4,
-       PCF50633_REGULATOR_LDO5,
-       PCF50633_REGULATOR_LDO6,
-       PCF50633_REGULATOR_HCLDO,
-       PCF50633_REGULATOR_MEMLDO,
-};
-
-#define PCF50633_REG_AUTOOUT   0x1a
-#define PCF50633_REG_DOWN1OUT  0x1e
-#define PCF50633_REG_DOWN2OUT  0x22
-#define PCF50633_REG_MEMLDOOUT 0x26
-#define PCF50633_REG_LDO1OUT   0x2d
-#define PCF50633_REG_LDO2OUT   0x2f
-#define PCF50633_REG_LDO3OUT   0x31
-#define PCF50633_REG_LDO4OUT   0x33
-#define PCF50633_REG_LDO5OUT   0x35
-#define PCF50633_REG_LDO6OUT   0x37
-#define PCF50633_REG_HCLDOOUT  0x39
+#include <linux/mfd/pcf50633/pmic.h>
 
 static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
        [PCF50633_REGULATOR_AUTO]       = PCF50633_REG_AUTOOUT,
index 048a3b903b013bcb5a0efb62c303e76c02ab1056..498286cbb5300d31f160b693e0f1d85ec254041f 100644 (file)
 #include <linux/slab.h>
 
 #include <linux/mfd/pcf50633/core.h>
-
-/* Two MBCS registers used during cold start */
-#define PCF50633_REG_MBCS1             0x4b
-#define PCF50633_REG_MBCS2             0x4c
-#define PCF50633_MBCS1_USBPRES                 0x01
-#define PCF50633_MBCS1_ADAPTPRES       0x01
+#include <linux/mfd/pcf50633/mbc.h>
 
 int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
                        void (*handler) (int, void *), void *data)
diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c
new file mode 100644 (file)
index 0000000..fa6f80f
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Interrupt driver for RICOH583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * based on code
+ *      Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mfd/rc5t583.h>
+
+enum int_type {
+       SYS_INT  = 0x1,
+       DCDC_INT = 0x2,
+       RTC_INT  = 0x4,
+       ADC_INT  = 0x8,
+       GPIO_INT = 0x10,
+};
+
+static int gpedge_add[] = {
+       RC5T583_GPIO_GPEDGE2,
+       RC5T583_GPIO_GPEDGE2
+};
+
+static int irq_en_add[] = {
+       RC5T583_INT_EN_SYS1,
+       RC5T583_INT_EN_SYS2,
+       RC5T583_INT_EN_DCDC,
+       RC5T583_INT_EN_RTC,
+       RC5T583_INT_EN_ADC1,
+       RC5T583_INT_EN_ADC2,
+       RC5T583_INT_EN_ADC3,
+       RC5T583_GPIO_EN_INT
+};
+
+static int irq_mon_add[] = {
+       RC5T583_INT_MON_SYS1,
+       RC5T583_INT_MON_SYS2,
+       RC5T583_INT_MON_DCDC,
+       RC5T583_INT_MON_RTC,
+       RC5T583_INT_IR_ADCL,
+       RC5T583_INT_IR_ADCH,
+       RC5T583_INT_IR_ADCEND,
+       RC5T583_INT_IR_GPIOF,
+       RC5T583_INT_IR_GPIOR
+};
+
+static int irq_clr_add[] = {
+       RC5T583_INT_IR_SYS1,
+       RC5T583_INT_IR_SYS2,
+       RC5T583_INT_IR_DCDC,
+       RC5T583_INT_IR_RTC,
+       RC5T583_INT_IR_ADCL,
+       RC5T583_INT_IR_ADCH,
+       RC5T583_INT_IR_ADCEND,
+       RC5T583_INT_IR_GPIOF,
+       RC5T583_INT_IR_GPIOR
+};
+
+static int main_int_type[] = {
+       SYS_INT,
+       SYS_INT,
+       DCDC_INT,
+       RTC_INT,
+       ADC_INT,
+       ADC_INT,
+       ADC_INT,
+       GPIO_INT,
+       GPIO_INT,
+};
+
+struct rc5t583_irq_data {
+       u8      int_type;
+       u8      master_bit;
+       u8      int_en_bit;
+       u8      mask_reg_index;
+       int     grp_index;
+};
+
+#define RC5T583_IRQ(_int_type, _master_bit, _grp_index, \
+                       _int_bit, _mask_ind)            \
+       {                                               \
+               .int_type       = _int_type,            \
+               .master_bit     = _master_bit,          \
+               .grp_index      = _grp_index,           \
+               .int_en_bit     = _int_bit,             \
+               .mask_reg_index = _mask_ind,            \
+       }
+
+static const struct rc5t583_irq_data rc5t583_irqs[RC5T583_MAX_IRQS] = {
+       [RC5T583_IRQ_ONKEY]             = RC5T583_IRQ(SYS_INT,  0, 0, 0, 0),
+       [RC5T583_IRQ_ACOK]              = RC5T583_IRQ(SYS_INT,  0, 1, 1, 0),
+       [RC5T583_IRQ_LIDOPEN]           = RC5T583_IRQ(SYS_INT,  0, 2, 2, 0),
+       [RC5T583_IRQ_PREOT]             = RC5T583_IRQ(SYS_INT,  0, 3, 3, 0),
+       [RC5T583_IRQ_CLKSTP]            = RC5T583_IRQ(SYS_INT,  0, 4, 4, 0),
+       [RC5T583_IRQ_ONKEY_OFF]         = RC5T583_IRQ(SYS_INT,  0, 5, 5, 0),
+       [RC5T583_IRQ_WD]                = RC5T583_IRQ(SYS_INT,  0, 7, 7, 0),
+       [RC5T583_IRQ_EN_PWRREQ1]        = RC5T583_IRQ(SYS_INT,  0, 8, 0, 1),
+       [RC5T583_IRQ_EN_PWRREQ2]        = RC5T583_IRQ(SYS_INT,  0, 9, 1, 1),
+       [RC5T583_IRQ_PRE_VINDET]        = RC5T583_IRQ(SYS_INT,  0, 10, 2, 1),
+
+       [RC5T583_IRQ_DC0LIM]            = RC5T583_IRQ(DCDC_INT, 1, 0, 0, 2),
+       [RC5T583_IRQ_DC1LIM]            = RC5T583_IRQ(DCDC_INT, 1, 1, 1, 2),
+       [RC5T583_IRQ_DC2LIM]            = RC5T583_IRQ(DCDC_INT, 1, 2, 2, 2),
+       [RC5T583_IRQ_DC3LIM]            = RC5T583_IRQ(DCDC_INT, 1, 3, 3, 2),
+
+       [RC5T583_IRQ_CTC]               = RC5T583_IRQ(RTC_INT,  2, 0, 0, 3),
+       [RC5T583_IRQ_YALE]              = RC5T583_IRQ(RTC_INT,  2, 5, 5, 3),
+       [RC5T583_IRQ_DALE]              = RC5T583_IRQ(RTC_INT,  2, 6, 6, 3),
+       [RC5T583_IRQ_WALE]              = RC5T583_IRQ(RTC_INT,  2, 7, 7, 3),
+
+       [RC5T583_IRQ_AIN1L]             = RC5T583_IRQ(ADC_INT,  3, 0, 0, 4),
+       [RC5T583_IRQ_AIN2L]             = RC5T583_IRQ(ADC_INT,  3, 1, 1, 4),
+       [RC5T583_IRQ_AIN3L]             = RC5T583_IRQ(ADC_INT,  3, 2, 2, 4),
+       [RC5T583_IRQ_VBATL]             = RC5T583_IRQ(ADC_INT,  3, 3, 3, 4),
+       [RC5T583_IRQ_VIN3L]             = RC5T583_IRQ(ADC_INT,  3, 4, 4, 4),
+       [RC5T583_IRQ_VIN8L]             = RC5T583_IRQ(ADC_INT,  3, 5, 5, 4),
+       [RC5T583_IRQ_AIN1H]             = RC5T583_IRQ(ADC_INT,  3, 6, 0, 5),
+       [RC5T583_IRQ_AIN2H]             = RC5T583_IRQ(ADC_INT,  3, 7, 1, 5),
+       [RC5T583_IRQ_AIN3H]             = RC5T583_IRQ(ADC_INT,  3, 8, 2, 5),
+       [RC5T583_IRQ_VBATH]             = RC5T583_IRQ(ADC_INT,  3, 9, 3, 5),
+       [RC5T583_IRQ_VIN3H]             = RC5T583_IRQ(ADC_INT,  3, 10, 4, 5),
+       [RC5T583_IRQ_VIN8H]             = RC5T583_IRQ(ADC_INT,  3, 11, 5, 5),
+       [RC5T583_IRQ_ADCEND]            = RC5T583_IRQ(ADC_INT,  3, 12, 0, 6),
+
+       [RC5T583_IRQ_GPIO0]             = RC5T583_IRQ(GPIO_INT, 4, 0, 0, 7),
+       [RC5T583_IRQ_GPIO1]             = RC5T583_IRQ(GPIO_INT, 4, 1, 1, 7),
+       [RC5T583_IRQ_GPIO2]             = RC5T583_IRQ(GPIO_INT, 4, 2, 2, 7),
+       [RC5T583_IRQ_GPIO3]             = RC5T583_IRQ(GPIO_INT, 4, 3, 3, 7),
+       [RC5T583_IRQ_GPIO4]             = RC5T583_IRQ(GPIO_INT, 4, 4, 4, 7),
+       [RC5T583_IRQ_GPIO5]             = RC5T583_IRQ(GPIO_INT, 4, 5, 5, 7),
+       [RC5T583_IRQ_GPIO6]             = RC5T583_IRQ(GPIO_INT, 4, 6, 6, 7),
+       [RC5T583_IRQ_GPIO7]             = RC5T583_IRQ(GPIO_INT, 4, 7, 7, 7),
+};
+
+static void rc5t583_irq_lock(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       mutex_lock(&rc5t583->irq_lock);
+}
+
+static void rc5t583_irq_unmask(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - rc5t583->irq_base;
+       const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
+
+       rc5t583->group_irq_en[data->grp_index] |= 1 << data->grp_index;
+       rc5t583->intc_inten_reg |= 1 << data->master_bit;
+       rc5t583->irq_en_reg[data->mask_reg_index] |= 1 << data->int_en_bit;
+}
+
+static void rc5t583_irq_mask(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - rc5t583->irq_base;
+       const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
+
+       rc5t583->group_irq_en[data->grp_index] &= ~(1 << data->grp_index);
+       if (!rc5t583->group_irq_en[data->grp_index])
+               rc5t583->intc_inten_reg &= ~(1 << data->master_bit);
+
+       rc5t583->irq_en_reg[data->mask_reg_index] &= ~(1 << data->int_en_bit);
+}
+
+static int rc5t583_irq_set_type(struct irq_data *irq_data, unsigned int type)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - rc5t583->irq_base;
+       const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
+       int val = 0;
+       int gpedge_index;
+       int gpedge_bit_pos;
+
+       /* Supporting only trigger level inetrrupt */
+       if ((data->int_type & GPIO_INT) && (type & IRQ_TYPE_EDGE_BOTH)) {
+               gpedge_index = data->int_en_bit / 4;
+               gpedge_bit_pos = data->int_en_bit % 4;
+
+               if (type & IRQ_TYPE_EDGE_FALLING)
+                       val |= 0x2;
+
+               if (type & IRQ_TYPE_EDGE_RISING)
+                       val |= 0x1;
+
+               rc5t583->gpedge_reg[gpedge_index] &= ~(3 << gpedge_bit_pos);
+               rc5t583->gpedge_reg[gpedge_index] |= (val << gpedge_bit_pos);
+               rc5t583_irq_unmask(irq_data);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static void rc5t583_irq_sync_unlock(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       int i;
+       int ret;
+
+       for (i = 0; i < ARRAY_SIZE(rc5t583->gpedge_reg); i++) {
+               ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
+                               rc5t583->gpedge_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               gpedge_add[i], ret);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(rc5t583->irq_en_reg); i++) {
+               ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
+                                       rc5t583->irq_en_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               irq_en_add[i], ret);
+       }
+
+       ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN,
+                               rc5t583->intc_inten_reg);
+       if (ret < 0)
+               dev_warn(rc5t583->dev,
+                       "Error in writing reg 0x%02x error: %d\n",
+                       RC5T583_INTC_INTEN, ret);
+
+       mutex_unlock(&rc5t583->irq_lock);
+}
+#ifdef CONFIG_PM_SLEEP
+static int rc5t583_irq_set_wake(struct irq_data *irq_data, unsigned int on)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       return irq_set_irq_wake(rc5t583->chip_irq, on);
+}
+#else
+#define rc5t583_irq_set_wake NULL
+#endif
+
+static irqreturn_t rc5t583_irq(int irq, void *data)
+{
+       struct rc5t583 *rc5t583 = data;
+       uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
+       uint8_t master_int;
+       int i;
+       int ret;
+       unsigned int rtc_int_sts = 0;
+
+       /* Clear the status */
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)
+               int_sts[i] = 0;
+
+       ret  = rc5t583_read(rc5t583->dev, RC5T583_INTC_INTMON, &master_int);
+       if (ret < 0) {
+               dev_err(rc5t583->dev,
+                       "Error in reading reg 0x%02x error: %d\n",
+                       RC5T583_INTC_INTMON, ret);
+               return IRQ_HANDLED;
+       }
+
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; ++i) {
+               if (!(master_int & main_int_type[i]))
+                       continue;
+
+               ret = rc5t583_read(rc5t583->dev, irq_mon_add[i], &int_sts[i]);
+               if (ret < 0) {
+                       dev_warn(rc5t583->dev,
+                               "Error in reading reg 0x%02x error: %d\n",
+                               irq_mon_add[i], ret);
+                       int_sts[i] = 0;
+                       continue;
+               }
+
+               if (main_int_type[i] & RTC_INT) {
+                       rtc_int_sts = 0;
+                       if (int_sts[i] & 0x1)
+                               rtc_int_sts |= BIT(6);
+                       if (int_sts[i] & 0x2)
+                               rtc_int_sts |= BIT(7);
+                       if (int_sts[i] & 0x4)
+                               rtc_int_sts |= BIT(0);
+                       if (int_sts[i] & 0x8)
+                               rtc_int_sts |= BIT(5);
+               }
+
+               ret = rc5t583_write(rc5t583->dev, irq_clr_add[i],
+                               ~int_sts[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in reading reg 0x%02x error: %d\n",
+                               irq_clr_add[i], ret);
+
+               if (main_int_type[i] & RTC_INT)
+                       int_sts[i] = rtc_int_sts;
+       }
+
+       /* Merge gpio interrupts for rising and falling case*/
+       int_sts[7] |= int_sts[8];
+
+       /* Call interrupt handler if enabled */
+       for (i = 0; i < RC5T583_MAX_IRQS; ++i) {
+               const struct rc5t583_irq_data *data = &rc5t583_irqs[i];
+               if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) &&
+                       (rc5t583->group_irq_en[data->master_bit] &
+                                       (1 << data->grp_index)))
+                       handle_nested_irq(rc5t583->irq_base + i);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct irq_chip rc5t583_irq_chip = {
+       .name = "rc5t583-irq",
+       .irq_mask = rc5t583_irq_mask,
+       .irq_unmask = rc5t583_irq_unmask,
+       .irq_bus_lock = rc5t583_irq_lock,
+       .irq_bus_sync_unlock = rc5t583_irq_sync_unlock,
+       .irq_set_type = rc5t583_irq_set_type,
+       .irq_set_wake = rc5t583_irq_set_wake,
+};
+
+int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base)
+{
+       int i, ret;
+
+       if (!irq_base) {
+               dev_warn(rc5t583->dev, "No interrupt support on IRQ base\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&rc5t583->irq_lock);
+
+       /* Initailize all int register to 0 */
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)  {
+               ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
+                               rc5t583->irq_en_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               irq_en_add[i], ret);
+       }
+
+       for (i = 0; i < RC5T583_MAX_GPEDGE_REG; i++)  {
+               ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
+                               rc5t583->gpedge_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               gpedge_add[i], ret);
+       }
+
+       ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN, 0x0);
+       if (ret < 0)
+               dev_warn(rc5t583->dev,
+                       "Error in writing reg 0x%02x error: %d\n",
+                       RC5T583_INTC_INTEN, ret);
+
+       /* Clear all interrupts in case they woke up active. */
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)  {
+               ret = rc5t583_write(rc5t583->dev, irq_clr_add[i], 0);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               irq_clr_add[i], ret);
+       }
+
+       rc5t583->irq_base = irq_base;
+       rc5t583->chip_irq = irq;
+
+       for (i = 0; i < RC5T583_MAX_IRQS; i++) {
+               int __irq = i + rc5t583->irq_base;
+               irq_set_chip_data(__irq, rc5t583);
+               irq_set_chip_and_handler(__irq, &rc5t583_irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(__irq, IRQF_VALID);
+#endif
+       }
+
+       ret = request_threaded_irq(irq, NULL, rc5t583_irq, IRQF_ONESHOT,
+                               "rc5t583", rc5t583);
+       if (ret < 0)
+               dev_err(rc5t583->dev,
+                       "Error in registering interrupt error: %d\n", ret);
+       return ret;
+}
+
+int rc5t583_irq_exit(struct rc5t583 *rc5t583)
+{
+       if (rc5t583->chip_irq)
+               free_irq(rc5t583->chip_irq, rc5t583);
+       return 0;
+}
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
new file mode 100644 (file)
index 0000000..99ef944
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Core driver access RC5T583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * Based on code
+ *     Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rc5t583.h>
+#include <linux/regmap.h>
+
+#define RICOH_ONOFFSEL_REG     0x10
+#define RICOH_SWCTL_REG                0x5E
+
+struct deepsleep_control_data {
+       u8 reg_add;
+       u8 ds_pos_bit;
+};
+
+#define DEEPSLEEP_INIT(_id, _reg, _pos)                \
+       {                                       \
+               .reg_add = RC5T583_##_reg,      \
+               .ds_pos_bit = _pos,             \
+       }
+
+static struct deepsleep_control_data deepsleep_data[] = {
+       DEEPSLEEP_INIT(DC0, SLPSEQ1, 0),
+       DEEPSLEEP_INIT(DC1, SLPSEQ1, 4),
+       DEEPSLEEP_INIT(DC2, SLPSEQ2, 0),
+       DEEPSLEEP_INIT(DC3, SLPSEQ2, 4),
+       DEEPSLEEP_INIT(LDO0, SLPSEQ3, 0),
+       DEEPSLEEP_INIT(LDO1, SLPSEQ3, 4),
+       DEEPSLEEP_INIT(LDO2, SLPSEQ4, 0),
+       DEEPSLEEP_INIT(LDO3, SLPSEQ4, 4),
+       DEEPSLEEP_INIT(LDO4, SLPSEQ5, 0),
+       DEEPSLEEP_INIT(LDO5, SLPSEQ5, 4),
+       DEEPSLEEP_INIT(LDO6, SLPSEQ6, 0),
+       DEEPSLEEP_INIT(LDO7, SLPSEQ6, 4),
+       DEEPSLEEP_INIT(LDO8, SLPSEQ7, 0),
+       DEEPSLEEP_INIT(LDO9, SLPSEQ7, 4),
+       DEEPSLEEP_INIT(PSO0, SLPSEQ8, 0),
+       DEEPSLEEP_INIT(PSO1, SLPSEQ8, 4),
+       DEEPSLEEP_INIT(PSO2, SLPSEQ9, 0),
+       DEEPSLEEP_INIT(PSO3, SLPSEQ9, 4),
+       DEEPSLEEP_INIT(PSO4, SLPSEQ10, 0),
+       DEEPSLEEP_INIT(PSO5, SLPSEQ10, 4),
+       DEEPSLEEP_INIT(PSO6, SLPSEQ11, 0),
+       DEEPSLEEP_INIT(PSO7, SLPSEQ11, 4),
+};
+
+#define EXT_PWR_REQ            \
+       (RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
+
+static struct mfd_cell rc5t583_subdevs[] = {
+       {.name = "rc5t583-regulator",},
+       {.name = "rc5t583-rtc",      },
+       {.name = "rc5t583-key",      }
+};
+
+int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_write(rc5t583->regmap, reg, val);
+}
+
+int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       unsigned int ival;
+       int ret;
+       ret = regmap_read(rc5t583->regmap, reg, &ival);
+       if (!ret)
+               *val = (uint8_t)ival;
+       return ret;
+}
+
+int rc5t583_set_bits(struct device *dev, unsigned int reg,
+                       unsigned int bit_mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
+}
+
+int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+                       unsigned int bit_mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
+}
+
+int rc5t583_update(struct device *dev, unsigned int reg,
+               unsigned int val, unsigned int mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, mask, val);
+}
+
+static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
+       int id, int ext_pwr, int slots)
+{
+       int ret;
+       uint8_t sleepseq_val;
+       unsigned int en_bit;
+       unsigned int slot_bit;
+
+       if (id == RC5T583_DS_DC0) {
+               dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id);
+               return -EINVAL;
+       }
+
+       en_bit = deepsleep_data[id].ds_pos_bit;
+       slot_bit = en_bit + 1;
+       ret = rc5t583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val);
+       if (ret < 0) {
+               dev_err(dev, "Error in reading reg 0x%x\n",
+                               deepsleep_data[id].reg_add);
+               return ret;
+       }
+
+       sleepseq_val &= ~(0xF << en_bit);
+       sleepseq_val |= BIT(en_bit);
+       sleepseq_val |= ((slots & 0x7) << slot_bit);
+       ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(1));
+       if (ret < 0) {
+               dev_err(dev, "Error in updating the 0x%02x register\n",
+                               RICOH_ONOFFSEL_REG);
+               return ret;
+       }
+
+       ret = rc5t583_write(dev, deepsleep_data[id].reg_add, sleepseq_val);
+       if (ret < 0) {
+               dev_err(dev, "Error in writing reg 0x%x\n",
+                               deepsleep_data[id].reg_add);
+               return ret;
+       }
+
+       if (id == RC5T583_DS_LDO4) {
+               ret = rc5t583_write(dev, RICOH_SWCTL_REG, 0x1);
+               if (ret < 0)
+                       dev_err(dev, "Error in writing reg 0x%x\n",
+                               RICOH_SWCTL_REG);
+       }
+       return ret;
+}
+
+static int __rc5t583_set_ext_pwrreq2_control(struct device *dev,
+       int id, int ext_pwr)
+{
+       int ret;
+
+       if (id != RC5T583_DS_DC0) {
+               dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id);
+               return -EINVAL;
+       }
+
+       ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(2));
+       if (ret < 0)
+               dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n");
+       return ret;
+}
+
+int rc5t583_ext_power_req_config(struct device *dev, int ds_id,
+       int ext_pwr_req, int deepsleep_slot_nr)
+{
+       if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ)
+               return -EINVAL;
+
+       if (ext_pwr_req & RC5T583_EXT_PWRREQ1_CONTROL)
+               return __rc5t583_set_ext_pwrreq1_control(dev, ds_id,
+                               ext_pwr_req, deepsleep_slot_nr);
+
+       if (ext_pwr_req & RC5T583_EXT_PWRREQ2_CONTROL)
+               return __rc5t583_set_ext_pwrreq2_control(dev,
+                       ds_id, ext_pwr_req);
+       return 0;
+}
+
+static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
+       struct rc5t583_platform_data *pdata)
+{
+       int ret;
+       int i;
+       uint8_t on_off_val = 0;
+
+       /*  Clear ONOFFSEL register */
+       if (pdata->enable_shutdown)
+               on_off_val = 0x1;
+
+       ret = rc5t583_write(rc5t583->dev, RICOH_ONOFFSEL_REG, on_off_val);
+       if (ret < 0)
+               dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
+                                       RICOH_ONOFFSEL_REG, ret);
+
+       ret = rc5t583_write(rc5t583->dev, RICOH_SWCTL_REG, 0x0);
+       if (ret < 0)
+               dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
+                                       RICOH_SWCTL_REG, ret);
+
+       /* Clear sleep sequence register */
+       for (i = RC5T583_SLPSEQ1; i <= RC5T583_SLPSEQ11; ++i) {
+               ret = rc5t583_write(rc5t583->dev, i, 0x0);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               i, ret);
+       }
+       return 0;
+}
+
+static bool volatile_reg(struct device *dev, unsigned int reg)
+{
+       /* Enable caching in interrupt registers */
+       switch (reg) {
+       case RC5T583_INT_EN_SYS1:
+       case RC5T583_INT_EN_SYS2:
+       case RC5T583_INT_EN_DCDC:
+       case RC5T583_INT_EN_RTC:
+       case RC5T583_INT_EN_ADC1:
+       case RC5T583_INT_EN_ADC2:
+       case RC5T583_INT_EN_ADC3:
+       case RC5T583_GPIO_GPEDGE1:
+       case RC5T583_GPIO_GPEDGE2:
+       case RC5T583_GPIO_EN_INT:
+               return false;
+
+       case RC5T583_GPIO_MON_IOIN:
+               /* This is gpio input register */
+               return true;
+
+       default:
+               /* Enable caching in gpio registers */
+               if ((reg >= RC5T583_GPIO_IOSEL) &&
+                               (reg <= RC5T583_GPIO_GPOFUNC))
+                       return false;
+
+               /* Enable caching in sleep seq registers */
+               if ((reg >= RC5T583_SLPSEQ1) && (reg <= RC5T583_SLPSEQ11))
+                       return false;
+
+               /* Enable caching of regulator registers */
+               if ((reg >= RC5T583_REG_DC0CTL) && (reg <= RC5T583_REG_SR3CTL))
+                       return false;
+               if ((reg >= RC5T583_REG_LDOEN1) &&
+                                       (reg <= RC5T583_REG_LDO9DAC_DS))
+                       return false;
+
+               break;
+       }
+
+       return true;
+}
+
+static const struct regmap_config rc5t583_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_reg = volatile_reg,
+       .max_register = RC5T583_MAX_REGS,
+       .num_reg_defaults_raw = RC5T583_MAX_REGS,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
+                             const struct i2c_device_id *id)
+{
+       struct rc5t583 *rc5t583;
+       struct rc5t583_platform_data *pdata = i2c->dev.platform_data;
+       int ret;
+       bool irq_init_success = false;
+
+       if (!pdata) {
+               dev_err(&i2c->dev, "Err: Platform data not found\n");
+               return -EINVAL;
+       }
+
+       rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL);
+       if (!rc5t583) {
+               dev_err(&i2c->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       rc5t583->dev = &i2c->dev;
+       i2c_set_clientdata(i2c, rc5t583);
+
+       rc5t583->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config);
+       if (IS_ERR(rc5t583->regmap)) {
+               ret = PTR_ERR(rc5t583->regmap);
+               dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = rc5t583_clear_ext_power_req(rc5t583, pdata);
+       if (ret < 0)
+               goto err_irq_init;
+
+       if (i2c->irq) {
+               ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base);
+               /* Still continue with waring if irq init fails */
+               if (ret)
+                       dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret);
+               else
+                       irq_init_success = true;
+       }
+
+       ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
+                       ARRAY_SIZE(rc5t583_subdevs), NULL, 0);
+       if (ret) {
+               dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
+               goto err_add_devs;
+       }
+
+       return 0;
+
+err_add_devs:
+       if (irq_init_success)
+               rc5t583_irq_exit(rc5t583);
+err_irq_init:
+       regmap_exit(rc5t583->regmap);
+       return ret;
+}
+
+static int  __devexit rc5t583_i2c_remove(struct i2c_client *i2c)
+{
+       struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
+
+       mfd_remove_devices(rc5t583->dev);
+       rc5t583_irq_exit(rc5t583);
+       regmap_exit(rc5t583->regmap);
+       return 0;
+}
+
+static const struct i2c_device_id rc5t583_i2c_id[] = {
+       {.name = "rc5t583", .driver_data = 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, rc5t583_i2c_id);
+
+static struct i2c_driver rc5t583_i2c_driver = {
+       .driver = {
+                  .name = "rc5t583",
+                  .owner = THIS_MODULE,
+                  },
+       .probe = rc5t583_i2c_probe,
+       .remove = __devexit_p(rc5t583_i2c_remove),
+       .id_table = rc5t583_i2c_id,
+};
+
+static int __init rc5t583_i2c_init(void)
+{
+       return i2c_add_driver(&rc5t583_i2c_driver);
+}
+subsys_initcall(rc5t583_i2c_init);
+
+static void __exit rc5t583_i2c_exit(void)
+{
+       i2c_del_driver(&rc5t583_i2c_driver);
+}
+
+module_exit(rc5t583_i2c_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("RICOH RC5T583 power management system device driver");
+MODULE_LICENSE("GPL v2");
index caadabeed8e94d59ae55fd8dbde84b37014769bb..48949d998d105f62172dae5697d3e4e3dd99819a 100644 (file)
 #include <linux/mfd/s5m87xx/s5m-rtc.h>
 #include <linux/regmap.h>
 
-static struct mfd_cell s5m87xx_devs[] = {
+static struct mfd_cell s5m8751_devs[] = {
+       {
+               .name = "s5m8751-pmic",
+       }, {
+               .name = "s5m-charger",
+       }, {
+               .name = "s5m8751-codec",
+       },
+};
+
+static struct mfd_cell s5m8763_devs[] = {
+       {
+               .name = "s5m8763-pmic",
+       }, {
+               .name = "s5m-rtc",
+       }, {
+               .name = "s5m-charger",
+       },
+};
+
+static struct mfd_cell s5m8767_devs[] = {
        {
                .name = "s5m8767-pmic",
        }, {
@@ -42,7 +62,7 @@ EXPORT_SYMBOL_GPL(s5m_reg_read);
 
 int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
 {
-       return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);;
+       return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(s5m_bulk_read);
 
@@ -54,7 +74,7 @@ EXPORT_SYMBOL_GPL(s5m_reg_write);
 
 int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
 {
-       return regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16));
+       return regmap_raw_write(s5m87xx->regmap, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(s5m_bulk_write);
 
@@ -74,10 +94,10 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c,
 {
        struct s5m_platform_data *pdata = i2c->dev.platform_data;
        struct s5m87xx_dev *s5m87xx;
-       int ret = 0;
-       int error;
+       int ret;
 
-       s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL);
+       s5m87xx = devm_kzalloc(&i2c->dev, sizeof(struct s5m87xx_dev),
+                               GFP_KERNEL);
        if (s5m87xx == NULL)
                return -ENOMEM;
 
@@ -96,9 +116,9 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c,
 
        s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config);
        if (IS_ERR(s5m87xx->regmap)) {
-               error = PTR_ERR(s5m87xx->regmap);
+               ret = PTR_ERR(s5m87xx->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
-                       error);
+                       ret);
                goto err;
        }
 
@@ -112,9 +132,23 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c,
 
        pm_runtime_set_active(s5m87xx->dev);
 
-       ret = mfd_add_devices(s5m87xx->dev, -1,
-                               s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs),
-                               NULL, 0);
+       switch (s5m87xx->device_type) {
+       case S5M8751X:
+               ret = mfd_add_devices(s5m87xx->dev, -1, s5m8751_devs,
+                                       ARRAY_SIZE(s5m8751_devs), NULL, 0);
+               break;
+       case S5M8763X:
+               ret = mfd_add_devices(s5m87xx->dev, -1, s5m8763_devs,
+                                       ARRAY_SIZE(s5m8763_devs), NULL, 0);
+               break;
+       case S5M8767X:
+               ret = mfd_add_devices(s5m87xx->dev, -1, s5m8767_devs,
+                                       ARRAY_SIZE(s5m8767_devs), NULL, 0);
+               break;
+       default:
+               /* If this happens the probe function is problem */
+               BUG();
+       }
 
        if (ret < 0)
                goto err;
@@ -126,7 +160,6 @@ err:
        s5m_irq_exit(s5m87xx);
        i2c_unregister_device(s5m87xx->rtc);
        regmap_exit(s5m87xx->regmap);
-       kfree(s5m87xx);
        return ret;
 }
 
@@ -138,7 +171,6 @@ static int s5m87xx_i2c_remove(struct i2c_client *i2c)
        s5m_irq_exit(s5m87xx);
        i2c_unregister_device(s5m87xx->rtc);
        regmap_exit(s5m87xx->regmap);
-       kfree(s5m87xx);
        return 0;
 }
 
index de76dfb6f0ad2af82796c74d4d16a9abe3701bb9..0236676085cf096f6c4e0091ac3803d4f8fc1f3f 100644 (file)
@@ -342,7 +342,10 @@ int s5m_irq_resume(struct s5m87xx_dev *s5m87xx)
                        s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx);
                        break;
                default:
-                       break;
+                       dev_err(s5m87xx->dev,
+                               "Unknown device type %d\n",
+                               s5m87xx->device_type);
+                       return -EINVAL;
 
                }
        }
@@ -444,7 +447,9 @@ int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
                }
                break;
        default:
-               break;
+               dev_err(s5m87xx->dev,
+                       "Unknown device type %d\n", s5m87xx->device_type);
+               return -EINVAL;
        }
 
        if (!s5m87xx->ono)
@@ -467,12 +472,15 @@ int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
                                        IRQF_ONESHOT, "s5m87xx-ono", s5m87xx);
                break;
        default:
+               ret = -EINVAL;
                break;
        }
 
-       if (ret)
+       if (ret) {
                dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
                        s5m87xx->ono, ret);
+               return ret;
+       }
 
        return 0;
 }
index f4d86117f44a21bcc140e93b8fd116798d6d5054..d927dd49acb340f303cf7e705e941863be8b312e 100644 (file)
@@ -387,14 +387,6 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
 
 EXPORT_SYMBOL_GPL(sm501_unit_power);
 
-
-/* Perform a rounded division. */
-static long sm501fb_round_div(long num, long denom)
-{
-        /* n / d + 1 / 2 = (2n + d) / 2d */
-        return (2 * num + denom) / (2 * denom);
-}
-
 /* clock value structure. */
 struct sm501_clock {
        unsigned long mclk;
@@ -428,7 +420,7 @@ static int sm501_calc_clock(unsigned long freq,
                /* try all 8 shift values.*/
                for (shift = 0; shift < 8; shift++) {
                        /* Calculate difference to requested clock */
-                       diff = sm501fb_round_div(mclk, divider << shift) - freq;
+                       diff = DIV_ROUND_CLOSEST(mclk, divider << shift) - freq;
                        if (diff < 0)
                                diff = -diff;
 
index e07947e56b2a0e2bd68d5aa7da434ae6aa5ed878..2dd8d49cb30bc7d63d14250e673b2c12eb4cef3f 100644 (file)
@@ -298,6 +298,11 @@ static struct mfd_cell stmpe_gpio_cell = {
        .num_resources  = ARRAY_SIZE(stmpe_gpio_resources),
 };
 
+static struct mfd_cell stmpe_gpio_cell_noirq = {
+       .name           = "stmpe-gpio",
+       /* gpio cell resources consist of an irq only so no resources here */
+};
+
 /*
  * Keypad (1601, 2401, 2403)
  */
@@ -346,6 +351,13 @@ static struct stmpe_variant_block stmpe801_blocks[] = {
        },
 };
 
+static struct stmpe_variant_block stmpe801_blocks_noirq[] = {
+       {
+               .cell   = &stmpe_gpio_cell_noirq,
+               .block  = STMPE_BLOCK_GPIO,
+       },
+};
+
 static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
                           bool enable)
 {
@@ -367,6 +379,17 @@ static struct stmpe_variant_info stmpe801 = {
        .enable         = stmpe801_enable,
 };
 
+static struct stmpe_variant_info stmpe801_noirq = {
+       .name           = "stmpe801",
+       .id_val         = STMPE801_ID,
+       .id_mask        = 0xffff,
+       .num_gpios      = 8,
+       .regs           = stmpe801_regs,
+       .blocks         = stmpe801_blocks_noirq,
+       .num_blocks     = ARRAY_SIZE(stmpe801_blocks_noirq),
+       .enable         = stmpe801_enable,
+};
+
 /*
  * Touchscreen (STMPE811 or STMPE610)
  */
@@ -712,7 +735,7 @@ static struct stmpe_variant_info stmpe2403 = {
        .enable_autosleep       = stmpe1601_autosleep, /* same as stmpe1601 */
 };
 
-static struct stmpe_variant_info *stmpe_variant_info[] = {
+static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
        [STMPE610]      = &stmpe610,
        [STMPE801]      = &stmpe801,
        [STMPE811]      = &stmpe811,
@@ -721,6 +744,16 @@ static struct stmpe_variant_info *stmpe_variant_info[] = {
        [STMPE2403]     = &stmpe2403,
 };
 
+/*
+ * These devices can be connected in a 'no-irq' configuration - the irq pin
+ * is not used and the device cannot interrupt the CPU. Here we only list
+ * devices which support this configuration - the driver will fail probing
+ * for any devices not listed here which are configured in this way.
+ */
+static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = {
+       [STMPE801]      = &stmpe801_noirq,
+};
+
 static irqreturn_t stmpe_irq(int irq, void *data)
 {
        struct stmpe *stmpe = data;
@@ -864,7 +897,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
        unsigned int irq_trigger = stmpe->pdata->irq_trigger;
        int autosleep_timeout = stmpe->pdata->autosleep_timeout;
        struct stmpe_variant_info *variant = stmpe->variant;
-       u8 icr;
+       u8 icr = 0;
        unsigned int id;
        u8 data[2];
        int ret;
@@ -887,31 +920,33 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
        if (ret)
                return ret;
 
-       if (id == STMPE801_ID)
-               icr = STMPE801_REG_SYS_CTRL_INT_EN;
-       else
-               icr = STMPE_ICR_LSB_GIM;
-
-       /* STMPE801 doesn't support Edge interrupts */
-       if (id != STMPE801_ID) {
-               if (irq_trigger == IRQF_TRIGGER_FALLING ||
-                               irq_trigger == IRQF_TRIGGER_RISING)
-                       icr |= STMPE_ICR_LSB_EDGE;
-       }
-
-       if (irq_trigger == IRQF_TRIGGER_RISING ||
-                       irq_trigger == IRQF_TRIGGER_HIGH) {
+       if (stmpe->irq >= 0) {
                if (id == STMPE801_ID)
-                       icr |= STMPE801_REG_SYS_CTRL_INT_HI;
+                       icr = STMPE801_REG_SYS_CTRL_INT_EN;
                else
-                       icr |= STMPE_ICR_LSB_HIGH;
-       }
+                       icr = STMPE_ICR_LSB_GIM;
 
-       if (stmpe->pdata->irq_invert_polarity) {
-               if (id == STMPE801_ID)
-                       icr ^= STMPE801_REG_SYS_CTRL_INT_HI;
-               else
-                       icr ^= STMPE_ICR_LSB_HIGH;
+               /* STMPE801 doesn't support Edge interrupts */
+               if (id != STMPE801_ID) {
+                       if (irq_trigger == IRQF_TRIGGER_FALLING ||
+                                       irq_trigger == IRQF_TRIGGER_RISING)
+                               icr |= STMPE_ICR_LSB_EDGE;
+               }
+
+               if (irq_trigger == IRQF_TRIGGER_RISING ||
+                               irq_trigger == IRQF_TRIGGER_HIGH) {
+                       if (id == STMPE801_ID)
+                               icr |= STMPE801_REG_SYS_CTRL_INT_HI;
+                       else
+                               icr |= STMPE_ICR_LSB_HIGH;
+               }
+
+               if (stmpe->pdata->irq_invert_polarity) {
+                       if (id == STMPE801_ID)
+                               icr ^= STMPE801_REG_SYS_CTRL_INT_HI;
+                       else
+                               icr ^= STMPE_ICR_LSB_HIGH;
+               }
        }
 
        if (stmpe->pdata->autosleep) {
@@ -1001,19 +1036,38 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
                stmpe->irq = ci->irq;
        }
 
+       if (stmpe->irq < 0) {
+               /* use alternate variant info for no-irq mode, if supported */
+               dev_info(stmpe->dev,
+                       "%s configured in no-irq mode by platform data\n",
+                       stmpe->variant->name);
+               if (!stmpe_noirq_variant_info[stmpe->partnum]) {
+                       dev_err(stmpe->dev,
+                               "%s does not support no-irq mode!\n",
+                               stmpe->variant->name);
+                       ret = -ENODEV;
+                       goto free_gpio;
+               }
+               stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
+       }
+
        ret = stmpe_chip_init(stmpe);
        if (ret)
                goto free_gpio;
 
-       ret = stmpe_irq_init(stmpe);
-       if (ret)
-               goto free_gpio;
+       if (stmpe->irq >= 0) {
+               ret = stmpe_irq_init(stmpe);
+               if (ret)
+                       goto free_gpio;
 
-       ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
-                       pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe);
-       if (ret) {
-               dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret);
-               goto out_removeirq;
+               ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
+                               pdata->irq_trigger | IRQF_ONESHOT,
+                               "stmpe", stmpe);
+               if (ret) {
+                       dev_err(stmpe->dev, "failed to request IRQ: %d\n",
+                                       ret);
+                       goto out_removeirq;
+               }
        }
 
        ret = stmpe_devices_init(stmpe);
@@ -1026,9 +1080,11 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
 
 out_removedevs:
        mfd_remove_devices(stmpe->dev);
-       free_irq(stmpe->irq, stmpe);
+       if (stmpe->irq >= 0)
+               free_irq(stmpe->irq, stmpe);
 out_removeirq:
-       stmpe_irq_remove(stmpe);
+       if (stmpe->irq >= 0)
+               stmpe_irq_remove(stmpe);
 free_gpio:
        if (pdata->irq_over_gpio)
                gpio_free(pdata->irq_gpio);
@@ -1041,8 +1097,10 @@ int stmpe_remove(struct stmpe *stmpe)
 {
        mfd_remove_devices(stmpe->dev);
 
-       free_irq(stmpe->irq, stmpe);
-       stmpe_irq_remove(stmpe);
+       if (stmpe->irq >= 0) {
+               free_irq(stmpe->irq, stmpe);
+               stmpe_irq_remove(stmpe);
+       }
 
        if (stmpe->pdata->irq_over_gpio)
                gpio_free(stmpe->pdata->irq_gpio);
@@ -1057,7 +1115,7 @@ static int stmpe_suspend(struct device *dev)
 {
        struct stmpe *stmpe = dev_get_drvdata(dev);
 
-       if (device_may_wakeup(dev))
+       if (stmpe->irq >= 0 && device_may_wakeup(dev))
                enable_irq_wake(stmpe->irq);
 
        return 0;
@@ -1067,7 +1125,7 @@ static int stmpe_resume(struct device *dev)
 {
        struct stmpe *stmpe = dev_get_drvdata(dev);
 
-       if (device_may_wakeup(dev))
+       if (stmpe->irq >= 0 && device_may_wakeup(dev))
                disable_irq_wake(stmpe->irq);
 
        return 0;
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
new file mode 100644 (file)
index 0000000..a66d4df
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Core driver for TI TPS65090 PMIC family
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65090.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+
+#define NUM_INT_REG 2
+#define TOTAL_NUM_REG 0x18
+
+/* interrupt status registers */
+#define TPS65090_INT_STS       0x0
+#define TPS65090_INT_STS2      0x1
+
+/* interrupt mask registers */
+#define TPS65090_INT_MSK       0x2
+#define TPS65090_INT_MSK2      0x3
+
+struct tps65090_irq_data {
+       u8              mask_reg;
+       u8              mask_pos;
+};
+
+#define TPS65090_IRQ(_reg, _mask_pos)          \
+       {                                       \
+               .mask_reg       = (_reg),       \
+               .mask_pos       = (_mask_pos),  \
+       }
+
+static const struct tps65090_irq_data tps65090_irqs[] = {
+       [0]             = TPS65090_IRQ(0, 0),
+       [1]             = TPS65090_IRQ(0, 1),
+       [2]             = TPS65090_IRQ(0, 2),
+       [3]             = TPS65090_IRQ(0, 3),
+       [4]             = TPS65090_IRQ(0, 4),
+       [5]             = TPS65090_IRQ(0, 5),
+       [6]             = TPS65090_IRQ(0, 6),
+       [7]             = TPS65090_IRQ(0, 7),
+       [8]             = TPS65090_IRQ(1, 0),
+       [9]             = TPS65090_IRQ(1, 1),
+       [10]            = TPS65090_IRQ(1, 2),
+       [11]            = TPS65090_IRQ(1, 3),
+       [12]            = TPS65090_IRQ(1, 4),
+       [13]            = TPS65090_IRQ(1, 5),
+       [14]            = TPS65090_IRQ(1, 6),
+       [15]            = TPS65090_IRQ(1, 7),
+};
+
+static struct mfd_cell tps65090s[] = {
+       {
+               .name = "tps65910-pmic",
+       },
+       {
+               .name = "tps65910-regulator",
+       },
+};
+
+struct tps65090 {
+       struct mutex            lock;
+       struct device           *dev;
+       struct i2c_client       *client;
+       struct regmap           *rmap;
+       struct irq_chip         irq_chip;
+       struct mutex            irq_lock;
+       int                     irq_base;
+       unsigned int            id;
+};
+
+int tps65090_write(struct device *dev, int reg, uint8_t val)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_write(tps->rmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(tps65090_write);
+
+int tps65090_read(struct device *dev, int reg, uint8_t *val)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       unsigned int temp_val;
+       int ret;
+       ret = regmap_read(tps->rmap, reg, &temp_val);
+       if (!ret)
+               *val = temp_val;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tps65090_read);
+
+int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u);
+}
+EXPORT_SYMBOL_GPL(tps65090_set_bits);
+
+int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u);
+}
+EXPORT_SYMBOL_GPL(tps65090_clr_bits);
+
+static void tps65090_irq_lock(struct irq_data *data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&tps65090->irq_lock);
+}
+
+static void tps65090_irq_mask(struct irq_data *irq_data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->hwirq;
+       const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
+
+       tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
+               data->mask_pos);
+}
+
+static void tps65090_irq_unmask(struct irq_data *irq_data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - tps65090->irq_base;
+       const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
+
+       tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
+               data->mask_pos);
+}
+
+static void tps65090_irq_sync_unlock(struct irq_data *data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
+
+       mutex_unlock(&tps65090->irq_lock);
+}
+
+static irqreturn_t tps65090_irq(int irq, void *data)
+{
+       struct tps65090 *tps65090 = data;
+       int ret = 0;
+       u8 status, mask;
+       unsigned long int acks = 0;
+       int i;
+
+       for (i = 0; i < NUM_INT_REG; i++) {
+               ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask);
+               if (ret < 0) {
+                       dev_err(tps65090->dev,
+                               "failed to read mask reg [addr:%d]\n",
+                               TPS65090_INT_MSK + i);
+                       return IRQ_NONE;
+               }
+               ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i,
+                       &status);
+               if (ret < 0) {
+                       dev_err(tps65090->dev,
+                               "failed to read status reg [addr:%d]\n",
+                                TPS65090_INT_STS + i);
+                       return IRQ_NONE;
+               }
+               if (status) {
+                       /* Ack only those interrupts which are not masked */
+                       status &= (~mask);
+                       ret = tps65090_write(tps65090->dev,
+                                       TPS65090_INT_STS + i, status);
+                       if (ret < 0) {
+                               dev_err(tps65090->dev,
+                                       "failed to write interrupt status\n");
+                               return IRQ_NONE;
+                       }
+                       acks |= (status << (i * 8));
+               }
+       }
+
+       for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs))
+               handle_nested_irq(tps65090->irq_base + i);
+       return acks ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
+       int irq_base)
+{
+       int i, ret;
+
+       if (!irq_base) {
+               dev_err(tps65090->dev, "IRQ base not set\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&tps65090->irq_lock);
+
+       for (i = 0; i < NUM_INT_REG; i++)
+               tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF);
+
+       for (i = 0; i < NUM_INT_REG; i++)
+               tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff);
+
+       tps65090->irq_base = irq_base;
+       tps65090->irq_chip.name = "tps65090";
+       tps65090->irq_chip.irq_mask = tps65090_irq_mask;
+       tps65090->irq_chip.irq_unmask = tps65090_irq_unmask;
+       tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock;
+       tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock;
+
+       for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
+               int __irq = i + tps65090->irq_base;
+               irq_set_chip_data(__irq, tps65090);
+               irq_set_chip_and_handler(__irq, &tps65090->irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(__irq, IRQF_VALID);
+#endif
+       }
+
+       ret = request_threaded_irq(irq, NULL, tps65090_irq, IRQF_ONESHOT,
+                               "tps65090", tps65090);
+       if (!ret) {
+               device_init_wakeup(tps65090->dev, 1);
+               enable_irq_wake(irq);
+       }
+
+       return ret;
+}
+
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS))
+               return true;
+       else
+               return false;
+}
+
+static const struct regmap_config tps65090_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = TOTAL_NUM_REG,
+       .num_reg_defaults_raw = TOTAL_NUM_REG,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_reg = is_volatile_reg,
+};
+
+static int __devinit tps65090_i2c_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct tps65090_platform_data *pdata = client->dev.platform_data;
+       struct tps65090 *tps65090;
+       int ret;
+
+       if (!pdata) {
+               dev_err(&client->dev, "tps65090 requires platform data\n");
+               return -EINVAL;
+       }
+
+       tps65090 = devm_kzalloc(&client->dev, sizeof(struct tps65090),
+               GFP_KERNEL);
+       if (tps65090 == NULL)
+               return -ENOMEM;
+
+       tps65090->client = client;
+       tps65090->dev = &client->dev;
+       i2c_set_clientdata(client, tps65090);
+
+       mutex_init(&tps65090->lock);
+
+       if (client->irq) {
+               ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base);
+               if (ret) {
+                       dev_err(&client->dev, "IRQ init failed with err: %d\n",
+                               ret);
+                       goto err_exit;
+               }
+       }
+
+       tps65090->rmap = regmap_init_i2c(tps65090->client,
+               &tps65090_regmap_config);
+       if (IS_ERR(tps65090->rmap)) {
+               dev_err(&client->dev, "regmap_init failed with err: %ld\n",
+                       PTR_ERR(tps65090->rmap));
+               goto err_irq_exit;
+       };
+
+       ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
+               ARRAY_SIZE(tps65090s), NULL, 0);
+       if (ret) {
+               dev_err(&client->dev, "add mfd devices failed with err: %d\n",
+                       ret);
+               goto err_regmap_exit;
+       }
+
+       return 0;
+
+err_regmap_exit:
+       regmap_exit(tps65090->rmap);
+
+err_irq_exit:
+       if (client->irq)
+               free_irq(client->irq, tps65090);
+err_exit:
+       return ret;
+}
+
+static int __devexit tps65090_i2c_remove(struct i2c_client *client)
+{
+       struct tps65090 *tps65090 = i2c_get_clientdata(client);
+
+       mfd_remove_devices(tps65090->dev);
+       regmap_exit(tps65090->rmap);
+       if (client->irq)
+               free_irq(client->irq, tps65090);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state)
+{
+       if (client->irq)
+               disable_irq(client->irq);
+       return 0;
+}
+
+static int tps65090_i2c_resume(struct i2c_client *client)
+{
+       if (client->irq)
+               enable_irq(client->irq);
+       return 0;
+}
+#endif
+
+static const struct i2c_device_id tps65090_id_table[] = {
+       { "tps65090", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, tps65090_id_table);
+
+static struct i2c_driver tps65090_driver = {
+       .driver = {
+               .name   = "tps65090",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tps65090_i2c_probe,
+       .remove         = __devexit_p(tps65090_i2c_remove),
+#ifdef CONFIG_PM
+       .suspend        = tps65090_i2c_suspend,
+       .resume         = tps65090_i2c_resume,
+#endif
+       .id_table       = tps65090_id_table,
+};
+
+static int __init tps65090_init(void)
+{
+       return i2c_add_driver(&tps65090_driver);
+}
+subsys_initcall(tps65090_init);
+
+static void __exit tps65090_exit(void)
+{
+       i2c_del_driver(&tps65090_driver);
+}
+module_exit(tps65090_exit);
+
+MODULE_DESCRIPTION("TPS65090 core driver");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
new file mode 100644 (file)
index 0000000..f7d854e
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * tps65217.c
+ *
+ * TPS65217 chip family multi-function driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65217.h>
+
+/**
+ * tps65217_reg_read: Read a single tps65217 register.
+ *
+ * @tps: Device to read from.
+ * @reg: Register to read.
+ * @val: Contians the value
+ */
+int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
+                       unsigned int *val)
+{
+       return regmap_read(tps->regmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(tps65217_reg_read);
+
+/**
+ * tps65217_reg_write: Write a single tps65217 register.
+ *
+ * @tps65217: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
+                       unsigned int val, unsigned int level)
+{
+       int ret;
+       unsigned int xor_reg_val;
+
+       switch (level) {
+       case TPS65217_PROTECT_NONE:
+               return regmap_write(tps->regmap, reg, val);
+       case TPS65217_PROTECT_L1:
+               xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
+               ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+
+               return regmap_write(tps->regmap, reg, val);
+       case TPS65217_PROTECT_L2:
+               xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
+               ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+               ret = regmap_write(tps->regmap, reg, val);
+               if (ret < 0)
+                       return ret;
+               ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+               return regmap_write(tps->regmap, reg, val);
+       default:
+               return -EINVAL;
+       }
+}
+EXPORT_SYMBOL_GPL(tps65217_reg_write);
+
+/**
+ * tps65217_update_bits: Modify bits w.r.t mask, val and level.
+ *
+ * @tps65217: Device to write to.
+ * @reg: Register to read-write to.
+ * @mask: Mask.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+int tps65217_update_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level)
+{
+       int ret;
+       unsigned int data;
+
+       ret = tps65217_reg_read(tps, reg, &data);
+       if (ret) {
+               dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
+               return ret;
+       }
+
+       data &= ~mask;
+       data |= val & mask;
+
+       ret = tps65217_reg_write(tps, reg, data, level);
+       if (ret)
+               dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
+
+       return ret;
+}
+
+int tps65217_set_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level)
+{
+       return tps65217_update_bits(tps, reg, mask, val, level);
+}
+EXPORT_SYMBOL_GPL(tps65217_set_bits);
+
+int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int level)
+{
+       return tps65217_update_bits(tps, reg, mask, 0, level);
+}
+EXPORT_SYMBOL_GPL(tps65217_clear_bits);
+
+static struct regmap_config tps65217_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int __devinit tps65217_probe(struct i2c_client *client,
+                               const struct i2c_device_id *ids)
+{
+       struct tps65217 *tps;
+       struct tps65217_board *pdata = client->dev.platform_data;
+       int i, ret;
+       unsigned int version;
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       tps->pdata = pdata;
+       tps->regmap = regmap_init_i2c(client, &tps65217_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(tps->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       i2c_set_clientdata(client, tps);
+       tps->dev = &client->dev;
+
+       ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
+       if (ret < 0) {
+               dev_err(tps->dev, "Failed to read revision"
+                                       " register: %d\n", ret);
+               goto err_regmap;
+       }
+
+       dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n",
+                       (version & TPS65217_CHIPID_CHIP_MASK) >> 4,
+                       version & TPS65217_CHIPID_REV_MASK);
+
+       for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
+               struct platform_device *pdev;
+
+               pdev = platform_device_alloc("tps65217-pmic", i);
+               if (!pdev) {
+                       dev_err(tps->dev, "Cannot create regulator %d\n", i);
+                       continue;
+               }
+
+               pdev->dev.parent = tps->dev;
+               platform_device_add_data(pdev, &pdata->tps65217_init_data[i],
+                                       sizeof(pdata->tps65217_init_data[i]));
+               tps->regulator_pdev[i] = pdev;
+
+               platform_device_add(pdev);
+       }
+
+       return 0;
+
+err_regmap:
+       regmap_exit(tps->regmap);
+
+       return ret;
+}
+
+static int __devexit tps65217_remove(struct i2c_client *client)
+{
+       struct tps65217 *tps = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
+               platform_device_unregister(tps->regulator_pdev[i]);
+
+       regmap_exit(tps->regmap);
+
+       return 0;
+}
+
+static const struct i2c_device_id tps65217_id_table[] = {
+       {"tps65217", 0xF0},
+       {/* end of list */}
+};
+MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
+
+static struct i2c_driver tps65217_driver = {
+       .driver         = {
+               .name   = "tps65217",
+       },
+       .id_table       = tps65217_id_table,
+       .probe          = tps65217_probe,
+       .remove         = __devexit_p(tps65217_remove),
+};
+
+static int __init tps65217_init(void)
+{
+       return i2c_add_driver(&tps65217_driver);
+}
+subsys_initcall(tps65217_init);
+
+static void __exit tps65217_exit(void)
+{
+       i2c_del_driver(&tps65217_driver);
+}
+module_exit(tps65217_exit);
+
+MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
+MODULE_DESCRIPTION("TPS65217 chip family multi-function driver");
+MODULE_LICENSE("GPL v2");
index 95c0d7978bec4a67cfaa74d8c93b430dc715974b..c9ed5c00a6211bb2349858ef76161eb880e45396 100644 (file)
@@ -145,12 +145,23 @@ static void tps65910_irq_disable(struct irq_data *data)
        tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq));
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tps65910_irq_set_wake(struct irq_data *data, unsigned int enable)
+{
+       struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
+       return irq_set_irq_wake(tps65910->chip_irq, enable);
+}
+#else
+#define tps65910_irq_set_wake NULL
+#endif
+
 static struct irq_chip tps65910_irq_chip = {
        .name = "tps65910",
        .irq_bus_lock = tps65910_irq_lock,
        .irq_bus_sync_unlock = tps65910_irq_sync_unlock,
        .irq_disable = tps65910_irq_disable,
        .irq_enable = tps65910_irq_enable,
+       .irq_set_wake = tps65910_irq_set_wake,
 };
 
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
index 4392f6bca156e20a71d7acb8cce0b9316db42753..bf2b25ebf2ca7d4c9c2777158518bd2a3185a39c 100644 (file)
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/mfd/core.h>
+#include <linux/regmap.h>
 #include <linux/mfd/tps65910.h>
 
 static struct mfd_cell tps65910s[] = {
@@ -38,99 +40,56 @@ static struct mfd_cell tps65910s[] = {
 static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
                                  int bytes, void *dest)
 {
-       struct i2c_client *i2c = tps65910->i2c_client;
-       struct i2c_msg xfer[2];
-       int ret;
-
-       /* Write register */
-       xfer[0].addr = i2c->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 1;
-       xfer[0].buf = &reg;
-
-       /* Read data */
-       xfer[1].addr = i2c->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = bytes;
-       xfer[1].buf = dest;
-
-       ret = i2c_transfer(i2c->adapter, xfer, 2);
-       if (ret == 2)
-               ret = 0;
-       else if (ret >= 0)
-               ret = -EIO;
-
-       return ret;
+       return regmap_bulk_read(tps65910->regmap, reg, dest, bytes);
 }
 
 static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
-                                  int bytes, void *src)
+                                 int bytes, void *src)
 {
-       struct i2c_client *i2c = tps65910->i2c_client;
-       /* we add 1 byte for device register */
-       u8 msg[TPS65910_MAX_REGISTER + 1];
-       int ret;
-
-       if (bytes > TPS65910_MAX_REGISTER)
-               return -EINVAL;
-
-       msg[0] = reg;
-       memcpy(&msg[1], src, bytes);
-
-       ret = i2c_master_send(i2c, msg, bytes + 1);
-       if (ret < 0)
-               return ret;
-       if (ret != bytes + 1)
-               return -EIO;
-       return 0;
+       return regmap_bulk_write(tps65910->regmap, reg, src, bytes);
 }
 
 int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
 {
-       u8 data;
-       int err;
-
-       mutex_lock(&tps65910->io_mutex);
-       err = tps65910_i2c_read(tps65910, reg, 1, &data);
-       if (err) {
-               dev_err(tps65910->dev, "read from reg %x failed\n", reg);
-               goto out;
-       }
-
-       data |= mask;
-       err = tps65910_i2c_write(tps65910, reg, 1, &data);
-       if (err)
-               dev_err(tps65910->dev, "write to reg %x failed\n", reg);
-
-out:
-       mutex_unlock(&tps65910->io_mutex);
-       return err;
+       return regmap_update_bits(tps65910->regmap, reg, mask, mask);
 }
 EXPORT_SYMBOL_GPL(tps65910_set_bits);
 
 int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
 {
-       u8 data;
-       int err;
-
-       mutex_lock(&tps65910->io_mutex);
-       err = tps65910_i2c_read(tps65910, reg, 1, &data);
-       if (err) {
-               dev_err(tps65910->dev, "read from reg %x failed\n", reg);
-               goto out;
-       }
-
-       data &= ~mask;
-       err = tps65910_i2c_write(tps65910, reg, 1, &data);
-       if (err)
-               dev_err(tps65910->dev, "write to reg %x failed\n", reg);
-
-out:
-       mutex_unlock(&tps65910->io_mutex);
-       return err;
+       return regmap_update_bits(tps65910->regmap, reg, mask, 0);
 }
 EXPORT_SYMBOL_GPL(tps65910_clear_bits);
 
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       struct tps65910 *tps65910 = dev_get_drvdata(dev);
+
+       /*
+        * Caching all regulator registers.
+        * All regualator register address range is same for
+        * TPS65910 and TPS65911
+        */
+       if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) {
+               /* Check for non-existing register */
+               if (tps65910_chip_id(tps65910) == TPS65910)
+                       if ((reg == TPS65911_VDDCTRL_OP) ||
+                               (reg == TPS65911_VDDCTRL_SR))
+                               return true;
+               return false;
+       }
+       return true;
+}
+
+static const struct regmap_config tps65910_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_reg = is_volatile_reg,
+       .max_register = TPS65910_MAX_REGISTER,
+       .num_reg_defaults_raw = TPS65910_MAX_REGISTER,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static int tps65910_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -161,6 +120,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        tps65910->write = tps65910_i2c_write;
        mutex_init(&tps65910->io_mutex);
 
+       tps65910->regmap = regmap_init_i2c(i2c, &tps65910_regmap_config);
+       if (IS_ERR(tps65910->regmap)) {
+               ret = PTR_ERR(tps65910->regmap);
+               dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+               goto regmap_err;
+       }
+
        ret = mfd_add_devices(tps65910->dev, -1,
                              tps65910s, ARRAY_SIZE(tps65910s),
                              NULL, 0);
@@ -178,6 +144,8 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        return ret;
 
 err:
+       regmap_exit(tps65910->regmap);
+regmap_err:
        kfree(tps65910);
        kfree(init_data);
        return ret;
@@ -189,6 +157,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
 
        tps65910_irq_exit(tps65910);
        mfd_remove_devices(tps65910->dev);
+       regmap_exit(tps65910->regmap);
        kfree(tps65910);
 
        return 0;
index 806680d1bbb4ec84237eaea15dbe645122dd91ea..7c2267e71f8b7f0e75fd2efeef472b85711f967c 100644 (file)
@@ -46,9 +46,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-#include <plat/cpu.h>
-#endif
+#include "twl-core.h"
 
 /*
  * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
 #define twl_has_watchdog()        false
 #endif
 
-#if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\
-       defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
+#if defined(CONFIG_MFD_TWL4030_AUDIO) || \
+       defined(CONFIG_MFD_TWL4030_AUDIO_MODULE)
 #define twl_has_codec()        true
 #else
 #define twl_has_codec()        false
 #define SUB_CHIP_ID1 1
 #define SUB_CHIP_ID2 2
 #define SUB_CHIP_ID3 3
+#define SUB_CHIP_ID_INVAL 0xff
 
 #define TWL_MODULE_LAST TWL4030_MODULE_LAST
 
-#define TWL4030_NR_IRQS    34 /* core:8, power:8, gpio: 18 */
-#define TWL6030_NR_IRQS    20
-
 /* Base Address defns for twl4030_map[] */
 
 /* subchip/slave 0 - USB ID */
@@ -314,7 +310,7 @@ static struct twl_mapping twl6030_map[] = {
         * so they continue to match the order in this table.
         */
        { SUB_CHIP_ID1, TWL6030_BASEADD_USB },
-       { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO },
+       { SUB_CHIP_ID_INVAL, TWL6030_BASEADD_AUDIO },
        { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID },
        { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
        { SUB_CHIP_ID1, TWL6030_BASEADD_PIH },
@@ -376,6 +372,11 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
                return -EPERM;
        }
        sid = twl_map[mod_no].sid;
+       if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
+               pr_err("%s: module %d is not part of the pmic\n",
+                      DRIVER_NAME, mod_no);
+               return -EINVAL;
+       }
        twl = &twl_modules[sid];
 
        mutex_lock(&twl->xfer_lock);
@@ -433,6 +434,11 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
                return -EPERM;
        }
        sid = twl_map[mod_no].sid;
+       if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
+               pr_err("%s: module %d is not part of the pmic\n",
+                      DRIVER_NAME, mod_no);
+               return -EINVAL;
+       }
        twl = &twl_modules[sid];
 
        mutex_lock(&twl->xfer_lock);
@@ -663,7 +669,8 @@ add_regulator(int num, struct regulator_init_data *pdata,
  */
 
 static int
-add_children(struct twl4030_platform_data *pdata, unsigned long features)
+add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
+               unsigned long features)
 {
        struct device   *child;
        unsigned sub_chip_id;
@@ -671,7 +678,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        if (twl_has_gpio() && pdata->gpio) {
                child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
                                pdata->gpio, sizeof(*pdata->gpio),
-                               false, pdata->irq_base + GPIO_INTR_OFFSET, 0);
+                               false, irq_base + GPIO_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -679,7 +686,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        if (twl_has_keypad() && pdata->keypad) {
                child = add_child(SUB_CHIP_ID2, "twl4030_keypad",
                                pdata->keypad, sizeof(*pdata->keypad),
-                               true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0);
+                               true, irq_base + KEYPAD_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -687,7 +694,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        if (twl_has_madc() && pdata->madc) {
                child = add_child(2, "twl4030_madc",
                                pdata->madc, sizeof(*pdata->madc),
-                               true, pdata->irq_base + MADC_INTR_OFFSET, 0);
+                               true, irq_base + MADC_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -703,7 +710,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                sub_chip_id = twl_map[TWL_MODULE_RTC].sid;
                child = add_child(sub_chip_id, "twl_rtc",
                                NULL, 0,
-                               true, pdata->irq_base + RTC_INTR_OFFSET, 0);
+                               true, irq_base + RTC_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -756,8 +763,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                                pdata->usb, sizeof(*pdata->usb),
                                true,
                                /* irq0 = USB_PRES, irq1 = USB */
-                               pdata->irq_base + USB_PRES_INTR_OFFSET,
-                               pdata->irq_base + USB_INTR_OFFSET);
+                               irq_base + USB_PRES_INTR_OFFSET,
+                               irq_base + USB_INTR_OFFSET);
 
                if (IS_ERR(child))
                        return PTR_ERR(child);
@@ -805,8 +812,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        pdata->usb, sizeof(*pdata->usb),
                        true,
                        /* irq1 = VBUS_PRES, irq0 = USB ID */
-                       pdata->irq_base + USBOTG_INTR_OFFSET,
-                       pdata->irq_base + USB_PRES_INTR_OFFSET);
+                       irq_base + USBOTG_INTR_OFFSET,
+                       irq_base + USB_PRES_INTR_OFFSET);
 
                if (IS_ERR(child))
                        return PTR_ERR(child);
@@ -833,7 +840,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 
        if (twl_has_pwrbutton() && twl_class_is_4030()) {
                child = add_child(1, "twl4030_pwrbutton",
-                               NULL, 0, true, pdata->irq_base + 8 + 0, 0);
+                               NULL, 0, true, irq_base + 8 + 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -847,15 +854,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        return PTR_ERR(child);
        }
 
-       if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
-               sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-               child = add_child(sub_chip_id, "twl6040",
-                               pdata->audio, sizeof(*pdata->audio),
-                               false, 0, 0);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-
        /* twl4030 regulators */
        if (twl_has_regulator() && twl_class_is_4030()) {
                child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
@@ -1092,8 +1090,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                child = add_child(3, "twl4030_bci",
                                pdata->bci, sizeof(*pdata->bci), false,
                                /* irq0 = CHG_PRES, irq1 = BCI */
-                               pdata->irq_base + BCI_PRES_INTR_OFFSET,
-                               pdata->irq_base + BCI_INTR_OFFSET);
+                               irq_base + BCI_PRES_INTR_OFFSET,
+                               irq_base + BCI_INTR_OFFSET);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -1193,26 +1191,24 @@ static void clocks_init(struct device *dev,
 
 /*----------------------------------------------------------------------*/
 
-int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
-int twl4030_exit_irq(void);
-int twl4030_init_chip_irq(const char *chip);
-int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
-int twl6030_exit_irq(void);
 
 static int twl_remove(struct i2c_client *client)
 {
-       unsigned i;
+       unsigned i, num_slaves;
        int status;
 
-       if (twl_class_is_4030())
+       if (twl_class_is_4030()) {
                status = twl4030_exit_irq();
-       else
+               num_slaves = TWL_NUM_SLAVES;
+       } else {
                status = twl6030_exit_irq();
+               num_slaves = TWL_NUM_SLAVES - 1;
+       }
 
        if (status < 0)
                return status;
 
-       for (i = 0; i < TWL_NUM_SLAVES; i++) {
+       for (i = 0; i < num_slaves; i++) {
                struct twl_client       *twl = &twl_modules[i];
 
                if (twl->client && twl->client != client)
@@ -1223,20 +1219,15 @@ static int twl_remove(struct i2c_client *client)
        return 0;
 }
 
-/* NOTE:  this driver only handles a single twl4030/tps659x0 chip */
+/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
 static int __devinit
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-       int                             status;
-       unsigned                        i;
        struct twl4030_platform_data    *pdata = client->dev.platform_data;
        struct device_node              *node = client->dev.of_node;
-       u8 temp;
-       int ret = 0;
-       int nr_irqs = TWL4030_NR_IRQS;
-
-       if ((id->driver_data) & TWL6030_CLASS)
-               nr_irqs = TWL6030_NR_IRQS;
+       int                             irq_base = 0;
+       int                             status;
+       unsigned                        i, num_slaves;
 
        if (node && !pdata) {
                /*
@@ -1255,17 +1246,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return -EINVAL;
        }
 
-       status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0);
-       if (IS_ERR_VALUE(status)) {
-               dev_err(&client->dev, "Fail to allocate IRQ descs\n");
-               return status;
-       }
-
-       pdata->irq_base = status;
-       pdata->irq_end = pdata->irq_base + nr_irqs;
-       irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0,
-                             &irq_domain_simple_ops, NULL);
-
        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
                dev_dbg(&client->dev, "can't talk I2C?\n");
                return -EIO;
@@ -1276,13 +1256,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return -EBUSY;
        }
 
-       for (i = 0; i < TWL_NUM_SLAVES; i++) {
-               struct twl_client       *twl = &twl_modules[i];
+       if ((id->driver_data) & TWL6030_CLASS) {
+               twl_id = TWL6030_CLASS_ID;
+               twl_map = &twl6030_map[0];
+               num_slaves = TWL_NUM_SLAVES - 1;
+       } else {
+               twl_id = TWL4030_CLASS_ID;
+               twl_map = &twl4030_map[0];
+               num_slaves = TWL_NUM_SLAVES;
+       }
+
+       for (i = 0; i < num_slaves; i++) {
+               struct twl_client *twl = &twl_modules[i];
 
                twl->address = client->addr + i;
-               if (i == 0)
+               if (i == 0) {
                        twl->client = client;
-               else {
+               else {
                        twl->client = i2c_new_dummy(client->adapter,
                                        twl->address);
                        if (!twl->client) {
@@ -1294,22 +1284,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                }
                mutex_init(&twl->xfer_lock);
        }
+
        inuse = true;
-       if ((id->driver_data) & TWL6030_CLASS) {
-               twl_id = TWL6030_CLASS_ID;
-               twl_map = &twl6030_map[0];
-       } else {
-               twl_id = TWL4030_CLASS_ID;
-               twl_map = &twl4030_map[0];
-       }
 
        /* setup clock framework */
        clocks_init(&client->dev, pdata->clock);
 
        /* read TWL IDCODE Register */
        if (twl_id == TWL4030_CLASS_ID) {
-               ret = twl_read_idcode_register();
-               WARN(ret < 0, "Error: reading twl_idcode register value\n");
+               status = twl_read_idcode_register();
+               WARN(status < 0, "Error: reading twl_idcode register value\n");
        }
 
        /* load power event scripts */
@@ -1317,31 +1301,31 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                twl4030_power_init(pdata->power);
 
        /* Maybe init the T2 Interrupt subsystem */
-       if (client->irq
-                       && pdata->irq_base
-                       && pdata->irq_end > pdata->irq_base) {
+       if (client->irq) {
                if (twl_class_is_4030()) {
                        twl4030_init_chip_irq(id->name);
-                       status = twl4030_init_irq(client->irq, pdata->irq_base,
-                       pdata->irq_end);
+                       irq_base = twl4030_init_irq(&client->dev, client->irq);
                } else {
-                       status = twl6030_init_irq(client->irq, pdata->irq_base,
-                       pdata->irq_end);
+                       irq_base = twl6030_init_irq(&client->dev, client->irq);
                }
 
-               if (status < 0)
+               if (irq_base < 0) {
+                       status = irq_base;
                        goto fail;
+               }
        }
 
-       /* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
+       /*
+        * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
         * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
         * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
         */
-
        if (twl_class_is_4030()) {
+               u8 temp;
+
                twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1);
                temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
-               I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
+                       I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
                twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
        }
 
@@ -1349,11 +1333,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (node)
                status = of_platform_populate(node, NULL, NULL, &client->dev);
        if (status)
-               status = add_children(pdata, id->driver_data);
+               status = add_children(pdata, irq_base, id->driver_data);
 
 fail:
        if (status < 0)
                twl_remove(client);
+
        return status;
 }
 
index 8c50a556e9866067eab7ec15c60d5e8736258fe6..6ff99dce714f1665e7021b5c266e68cb8e857851 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef __TWL_CORE_H__
 #define __TWL_CORE_H__
 
-extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
+extern int twl6030_init_irq(struct device *dev, int irq_num);
 extern int twl6030_exit_irq(void);
-extern int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
+extern int twl4030_init_irq(struct device *dev, int irq_num);
 extern int twl4030_exit_irq(void);
 extern int twl4030_init_chip_irq(const char *chip);
 
index b69bb517b102a4595b76342afeb58e0c9b3270c2..5d656e8143583634196061e709dcd1944d0b1121 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
-
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 #include <linux/i2c/twl.h>
 
 #include "twl-core.h"
  *     base + 8  .. base + 15  SIH for PWR_INT
  *     base + 16 .. base + 33  SIH for GPIO
  */
+#define TWL4030_CORE_NR_IRQS   8
+#define TWL4030_PWR_NR_IRQS    8
 
 /* PIH register offsets */
 #define REG_PIH_ISR_P1                 0x01
 #define REG_PIH_ISR_P2                 0x02
 #define REG_PIH_SIR                    0x03    /* for testing */
 
-
 /* Linux could (eventually) use either IRQ line */
 static int irq_line;
 
@@ -111,7 +114,8 @@ static int nr_sih_modules;
 #define TWL4030_MODULE_INT_PWR         TWL4030_MODULE_INT
 
 
-/* Order in this table matches order in PIH_ISR.  That is,
+/*
+ * Order in this table matches order in PIH_ISR.  That is,
  * BIT(n) in PIH_ISR is sih_modules[n].
  */
 /* sih_modules_twl4030 is used both in twl4030 and twl5030 */
@@ -288,7 +292,6 @@ static unsigned twl4030_irq_base;
  */
 static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 {
-       int             module_irq;
        irqreturn_t     ret;
        u8              pih_isr;
 
@@ -299,16 +302,18 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
                return IRQ_NONE;
        }
 
-       /* these handlers deal with the relevant SIH irq status */
-       for (module_irq = twl4030_irq_base;
-                       pih_isr;
-                       pih_isr >>= 1, module_irq++) {
-               if (pih_isr & 0x1)
-                       handle_nested_irq(module_irq);
+       while (pih_isr) {
+               unsigned long   pending = __ffs(pih_isr);
+               unsigned int    irq;
+
+               pih_isr &= ~BIT(pending);
+               irq = pending + twl4030_irq_base;
+               handle_nested_irq(irq);
        }
 
        return IRQ_HANDLED;
 }
+
 /*----------------------------------------------------------------------*/
 
 /*
@@ -337,7 +342,6 @@ static int twl4030_init_sih_modules(unsigned line)
        memset(buf, 0xff, sizeof buf);
        sih = sih_modules;
        for (i = 0; i < nr_sih_modules; i++, sih++) {
-
                /* skip USB -- it's funky */
                if (!sih->bytes_ixr)
                        continue;
@@ -352,7 +356,8 @@ static int twl4030_init_sih_modules(unsigned line)
                        pr_err("twl4030: err %d initializing %s %s\n",
                                        status, sih->name, "IMR");
 
-               /* Maybe disable "exclusive" mode; buffer second pending irq;
+               /*
+                * Maybe disable "exclusive" mode; buffer second pending irq;
                 * set Clear-On-Read (COR) bit.
                 *
                 * NOTE that sometimes COR polarity is documented as being
@@ -382,7 +387,8 @@ static int twl4030_init_sih_modules(unsigned line)
                if (sih->irq_lines <= line)
                        continue;
 
-               /* Clear pending interrupt status.  Either the read was
+               /*
+                * Clear pending interrupt status.  Either the read was
                 * enough, or we need to write those bits.  Repeat, in
                 * case an IRQ is pending (PENDDIS=0) ... that's not
                 * uncommon with PWR_INT.PWRON.
@@ -398,7 +404,8 @@ static int twl4030_init_sih_modules(unsigned line)
                                status = twl_i2c_write(sih->module, buf,
                                        sih->mask[line].isr_offset,
                                        sih->bytes_ixr);
-                       /* else COR=1 means read sufficed.
+                       /*
+                        * else COR=1 means read sufficed.
                         * (for most SIH modules...)
                         */
                }
@@ -410,7 +417,8 @@ static int twl4030_init_sih_modules(unsigned line)
 static inline void activate_irq(int irq)
 {
 #ifdef CONFIG_ARM
-       /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+       /*
+        * ARM requires an extra step to clear IRQ_NOREQUEST, which it
         * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
         */
        set_irq_flags(irq, IRQF_VALID);
@@ -620,33 +628,24 @@ static irqreturn_t handle_twl4030_sih(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static unsigned twl4030_irq_next;
-
-/* returns the first IRQ used by this SIH bank,
- * or negative errno
- */
-int twl4030_sih_setup(int module)
+/* returns the first IRQ used by this SIH bank, or negative errno */
+int twl4030_sih_setup(struct device *dev, int module, int irq_base)
 {
        int                     sih_mod;
        const struct sih        *sih = NULL;
        struct sih_agent        *agent;
        int                     i, irq;
        int                     status = -EINVAL;
-       unsigned                irq_base = twl4030_irq_next;
 
        /* only support modules with standard clear-on-read for now */
-       for (sih_mod = 0, sih = sih_modules;
-                       sih_mod < nr_sih_modules;
+       for (sih_mod = 0, sih = sih_modules; sih_mod < nr_sih_modules;
                        sih_mod++, sih++) {
                if (sih->module == module && sih->set_cor) {
-                       if (!WARN((irq_base + sih->bits) > NR_IRQS,
-                                       "irq %d for %s too big\n",
-                                       irq_base + sih->bits,
-                                       sih->name))
-                               status = 0;
+                       status = 0;
                        break;
                }
        }
+
        if (status < 0)
                return status;
 
@@ -654,8 +653,6 @@ int twl4030_sih_setup(int module)
        if (!agent)
                return -ENOMEM;
 
-       status = 0;
-
        agent->irq_base = irq_base;
        agent->sih = sih;
        agent->imr = ~0;
@@ -671,8 +668,6 @@ int twl4030_sih_setup(int module)
                activate_irq(irq);
        }
 
-       twl4030_irq_next += i;
-
        /* replace generic PIH handler (handle_simple_irq) */
        irq = sih_mod + twl4030_irq_base;
        irq_set_handler_data(irq, agent);
@@ -680,26 +675,43 @@ int twl4030_sih_setup(int module)
        status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
                                      agent->irq_name ?: sih->name, NULL);
 
-       pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
-                       irq, irq_base, twl4030_irq_next - 1);
+       dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
+                       irq, irq_base, irq_base + i - 1);
 
        return status < 0 ? status : irq_base;
 }
 
 /* FIXME need a call to reverse twl4030_sih_setup() ... */
 
-
 /*----------------------------------------------------------------------*/
 
 /* FIXME pass in which interrupt line we'll use ... */
 #define twl_irq_line   0
 
-int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
+int twl4030_init_irq(struct device *dev, int irq_num)
 {
        static struct irq_chip  twl4030_irq_chip;
+       int                     status, i;
+       int                     irq_base, irq_end, nr_irqs;
+       struct                  device_node *node = dev->of_node;
 
-       int                     status;
-       int                     i;
+       /*
+        * TWL core and pwr interrupts must be contiguous because
+        * the hwirqs numbers are defined contiguously from 1 to 15.
+        * Create only one domain for both.
+        */
+       nr_irqs = TWL4030_PWR_NR_IRQS + TWL4030_CORE_NR_IRQS;
+
+       irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+       if (IS_ERR_VALUE(irq_base)) {
+               dev_err(dev, "Fail to allocate IRQ descs\n");
+               return irq_base;
+       }
+
+       irq_domain_add_legacy(node, nr_irqs, irq_base, 0,
+                             &irq_domain_simple_ops, NULL);
+
+       irq_end = irq_base + TWL4030_CORE_NR_IRQS;
 
        /*
         * Mask and clear all TWL4030 interrupts since initially we do
@@ -711,7 +723,8 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
 
        twl4030_irq_base = irq_base;
 
-       /* install an irq handler for each of the SIH modules;
+       /*
+        * Install an irq handler for each of the SIH modules;
         * clone dummy irq_chip since PIH can't *do* anything
         */
        twl4030_irq_chip = dummy_irq_chip;
@@ -725,14 +738,14 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                irq_set_nested_thread(i, 1);
                activate_irq(i);
        }
-       twl4030_irq_next = i;
-       pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
-                       irq_num, irq_base, twl4030_irq_next - 1);
+
+       dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", "PIH",
+                       irq_num, irq_base, irq_end);
 
        /* ... and the PWR_INT module ... */
-       status = twl4030_sih_setup(TWL4030_MODULE_INT);
+       status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end);
        if (status < 0) {
-               pr_err("twl4030: sih_setup PWR INT --> %d\n", status);
+               dev_err(dev, "sih_setup PWR INT --> %d\n", status);
                goto fail;
        }
 
@@ -741,11 +754,11 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                                      IRQF_ONESHOT,
                                      "TWL4030-PIH", NULL);
        if (status < 0) {
-               pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
+               dev_err(dev, "could not claim irq%d: %d\n", irq_num, status);
                goto fail_rqirq;
        }
 
-       return status;
+       return irq_base;
 fail_rqirq:
        /* clean up twl4030_sih_setup */
 fail:
index c6b456ad7342755c83e4f31d1106dd9d74cf5ca6..b76902f1e44ae545af5e562765259834f3eed7db 100644 (file)
@@ -39,6 +39,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 
 #include "twl-core.h"
 
@@ -51,8 +53,8 @@
  *
  * We set up IRQs starting at a platform-specified base. An interrupt map table,
  * specifies mapping between interrupt number and the associated module.
- *
  */
+#define TWL6030_NR_IRQS    20
 
 static int twl6030_interrupt_mapping[24] = {
        PWR_INTR_OFFSET,        /* Bit 0        PWRON                   */
@@ -185,8 +187,17 @@ static int twl6030_irq_thread(void *data)
                        }
                local_irq_enable();
                }
-               ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
-                               REG_INT_STS_A, 3); /* clear INT_STS_A */
+
+               /*
+                * NOTE:
+                * Simulation confirms that documentation is wrong w.r.t the
+                * interrupt status clear operation. A single *byte* write to
+                * any one of STS_A to STS_C register results in all three
+                * STS registers being reset. Since it does not matter which
+                * value is written, all three registers are cleared on a
+                * single byte write, so we just use 0x0 to clear.
+                */
+               ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
                if (ret)
                        pr_warning("twl6030: I2C error in clearing PIH ISR\n");
 
@@ -227,7 +238,7 @@ static inline void activate_irq(int irq)
 #endif
 }
 
-int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
+static int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
 {
        if (on)
                atomic_inc(&twl6030_wakeirqs);
@@ -237,11 +248,6 @@ int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
        return 0;
 }
 
-/*----------------------------------------------------------------------*/
-
-static unsigned twl6030_irq_next;
-
-/*----------------------------------------------------------------------*/
 int twl6030_interrupt_unmask(u8 bit_mask, u8 offset)
 {
        int ret;
@@ -311,7 +317,8 @@ int twl6030_mmc_card_detect_config(void)
                                                                        ret);
                return ret;
        }
-       return 0;
+
+       return twl6030_irq_base + MMCDETECT_INTR_OFFSET;
 }
 EXPORT_SYMBOL(twl6030_mmc_card_detect_config);
 
@@ -340,29 +347,44 @@ int twl6030_mmc_card_detect(struct device *dev, int slot)
 }
 EXPORT_SYMBOL(twl6030_mmc_card_detect);
 
-int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
+int twl6030_init_irq(struct device *dev, int irq_num)
 {
-
-       int     status = 0;
-       int     i;
+       struct                  device_node *node = dev->of_node;
+       int                     nr_irqs, irq_base, irq_end;
        struct task_struct      *task;
-       int ret;
-       u8 mask[4];
+       static struct irq_chip  twl6030_irq_chip;
+       int                     status = 0;
+       int                     i;
+       u8                      mask[4];
+
+       nr_irqs = TWL6030_NR_IRQS;
+
+       irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+       if (IS_ERR_VALUE(irq_base)) {
+               dev_err(dev, "Fail to allocate IRQ descs\n");
+               return irq_base;
+       }
+
+       irq_domain_add_legacy(node, nr_irqs, irq_base, 0,
+                             &irq_domain_simple_ops, NULL);
+
+       irq_end = irq_base + nr_irqs;
 
-       static struct irq_chip  twl6030_irq_chip;
        mask[1] = 0xFF;
        mask[2] = 0xFF;
        mask[3] = 0xFF;
-       ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
-                       REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */
-       ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
-                       REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */
-       ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
-                       REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */
+
+       /* mask all int lines */
+       twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3);
+       /* mask all int sts */
+       twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3);
+       /* clear INT_STS_A,B,C */
+       twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3);
 
        twl6030_irq_base = irq_base;
 
-       /* install an irq handler for each of the modules;
+       /*
+        * install an irq handler for each of the modules;
         * clone dummy irq_chip since PIH can't *do* anything
         */
        twl6030_irq_chip = dummy_irq_chip;
@@ -377,30 +399,29 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                activate_irq(i);
        }
 
-       twl6030_irq_next = i;
-       pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
-                       irq_num, irq_base, twl6030_irq_next - 1);
+       dev_info(dev, "PIH (irq %d) chaining IRQs %d..%d\n",
+                       irq_num, irq_base, irq_end);
 
        /* install an irq handler to demultiplex the TWL6030 interrupt */
        init_completion(&irq_event);
 
-       status = request_irq(irq_num, handle_twl6030_pih, 0,
-                               "TWL6030-PIH", &irq_event);
+       status = request_irq(irq_num, handle_twl6030_pih, 0, "TWL6030-PIH",
+                            &irq_event);
        if (status < 0) {
-               pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
+               dev_err(dev, "could not claim irq %d: %d\n", irq_num, status);
                goto fail_irq;
        }
 
        task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
        if (IS_ERR(task)) {
-               pr_err("twl6030: could not create irq %d thread!\n", irq_num);
+               dev_err(dev, "could not create irq %d thread!\n", irq_num);
                status = PTR_ERR(task);
                goto fail_kthread;
        }
 
        twl_irq = irq_num;
        register_pm_notifier(&twl6030_irq_pm_notifier_block);
-       return status;
+       return irq_base;
 
 fail_kthread:
        free_irq(irq_num, &irq_event);
@@ -408,6 +429,7 @@ fail_kthread:
 fail_irq:
        for (i = irq_base; i < irq_end; i++)
                irq_set_chip_and_handler(i, NULL, NULL);
+
        return status;
 }
 
index 745c8794566426ad6de06b465c38744d5851ec66..4bceee98f0a4f848a417217f87dbb31bc8d7594f 100644 (file)
@@ -89,7 +89,7 @@ static const struct spi_device_id wm831x_spi_ids[] = {
        { "wm8326", WM8326 },
        { },
 };
-MODULE_DEVICE_TABLE(spi, wm831x_spi_id);
+MODULE_DEVICE_TABLE(spi, wm831x_spi_ids);
 
 static struct spi_driver wm831x_spi_driver = {
        .driver = {
index 237764ae5f9bdb8deaa5a276e4cd902dcfa065a5..1189a17f0f25f6362b5d97c2ff65e8d7cd685c5f 100644 (file)
@@ -271,8 +271,7 @@ static int wm8400_init(struct wm8400 *wm8400,
                return -EIO;
        }
        if (i != reg_data[WM8400_RESET_ID].default_val) {
-               dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
-                       reg);
+               dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n", i);
                return -ENODEV;
        }
 
index 98733d408feec58f719da3842a7b13387fc42db8..9d7ca1e978fad30775d1de8b6913333a137118c6 100644 (file)
@@ -639,7 +639,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
        }
 
        pm_runtime_enable(wm8994->dev);
-       pm_runtime_resume(wm8994->dev);
+       pm_runtime_idle(wm8994->dev);
 
        return 0;
 
index 7605b60954539fa14b9203e5f6b3343475676390..bfd25af6ecb106e75eddb4cdc0afad561238506f 100644 (file)
@@ -20,7 +20,6 @@
 #include "wm8994.h"
 
 static struct reg_default wm1811_defaults[] = {
-       { 0x0000, 0x1811 },    /* R0    - Software Reset */
        { 0x0001, 0x0000 },    /* R1    - Power Management (1) */
        { 0x0002, 0x6000 },    /* R2    - Power Management (2) */
        { 0x0003, 0x0000 },    /* R3    - Power Management (3) */
@@ -61,7 +60,7 @@ static struct reg_default wm1811_defaults[] = {
        { 0x0036, 0x0000 },    /* R54   - Speaker Mixer */
        { 0x0037, 0x0000 },    /* R55   - Additional Control */
        { 0x0038, 0x0000 },    /* R56   - AntiPOP (1) */
-       { 0x0039, 0x0180 },    /* R57   - AntiPOP (2) */
+       { 0x0039, 0x0000 },    /* R57   - AntiPOP (2) */
        { 0x003B, 0x000D },    /* R59   - LDO 1 */
        { 0x003C, 0x0003 },    /* R60   - LDO 2 */
        { 0x003D, 0x0039 },    /* R61   - MICBIAS1 */
@@ -69,16 +68,12 @@ static struct reg_default wm1811_defaults[] = {
        { 0x004C, 0x1F25 },    /* R76   - Charge Pump (1) */
        { 0x004D, 0xAB19 },    /* R77   - Charge Pump (2) */
        { 0x0051, 0x0004 },    /* R81   - Class W (1) */
-       { 0x0054, 0x0000 },    /* R84   - DC Servo (1) */
        { 0x0055, 0x054A },    /* R85   - DC Servo (2) */
-       { 0x0058, 0x0000 },    /* R88   - DC Servo Readback */
        { 0x0059, 0x0000 },    /* R89   - DC Servo (4) */
        { 0x0060, 0x0000 },    /* R96   - Analogue HP (1) */
        { 0x00C5, 0x0000 },    /* R197  - Class D Test (5) */
        { 0x00D0, 0x7600 },    /* R208  - Mic Detect 1 */
        { 0x00D1, 0x007F },    /* R209  - Mic Detect 2 */
-       { 0x00D2, 0x0000 },    /* R210  - Mic Detect 3 */
-       { 0x0100, 0x0100 },    /* R256  - Chip Revision */
        { 0x0101, 0x8004 },    /* R257  - Control Interface */
        { 0x0200, 0x0000 },    /* R512  - AIF1 Clocking (1) */
        { 0x0201, 0x0000 },    /* R513  - AIF1 Clocking (2) */
@@ -88,7 +83,6 @@ static struct reg_default wm1811_defaults[] = {
        { 0x0209, 0x0000 },    /* R521  - Clocking (2) */
        { 0x0210, 0x0083 },    /* R528  - AIF1 Rate */
        { 0x0211, 0x0083 },    /* R529  - AIF2 Rate */
-       { 0x0212, 0x0000 },    /* R530  - Rate Status */
        { 0x0220, 0x0000 },    /* R544  - FLL1 Control (1) */
        { 0x0221, 0x0000 },    /* R545  - FLL1 Control (2) */
        { 0x0222, 0x0000 },    /* R546  - FLL1 Control (3) */
@@ -218,8 +212,6 @@ static struct reg_default wm1811_defaults[] = {
        { 0x070A, 0xA101 },    /* R1802 - GPIO 11 */
        { 0x0720, 0x0000 },    /* R1824 - Pull Control (1) */
        { 0x0721, 0x0156 },    /* R1825 - Pull Control (2) */
-       { 0x0730, 0x0000 },    /* R1840 - Interrupt Status 1 */
-       { 0x0731, 0x0000 },    /* R1841 - Interrupt Status 2 */
        { 0x0732, 0x0000 },    /* R1842 - Interrupt Raw Status 2 */
        { 0x0738, 0x07FF },    /* R1848 - Interrupt Status 1 Mask */
        { 0x0739, 0xDFEF },    /* R1849 - Interrupt Status 2 Mask */
@@ -228,7 +220,6 @@ static struct reg_default wm1811_defaults[] = {
 };
 
 static struct reg_default wm8994_defaults[] = {
-       { 0x0000, 0x8994 },    /* R0     - Software Reset */ 
        { 0x0001, 0x0000 },    /* R1     - Power Management (1) */ 
        { 0x0002, 0x6000 },    /* R2     - Power Management (2) */ 
        { 0x0003, 0x0000 },    /* R3     - Power Management (3) */ 
@@ -275,12 +266,9 @@ static struct reg_default wm8994_defaults[] = {
        { 0x003C, 0x0003 },    /* R60    - LDO 2 */ 
        { 0x004C, 0x1F25 },    /* R76    - Charge Pump (1) */ 
        { 0x0051, 0x0004 },    /* R81    - Class W (1) */ 
-       { 0x0054, 0x0000 },    /* R84    - DC Servo (1) */ 
        { 0x0055, 0x054A },    /* R85    - DC Servo (2) */ 
        { 0x0057, 0x0000 },    /* R87    - DC Servo (4) */ 
-       { 0x0058, 0x0000 },    /* R88    - DC Servo Readback */ 
        { 0x0060, 0x0000 },    /* R96    - Analogue HP (1) */ 
-       { 0x0100, 0x0003 },    /* R256   - Chip Revision */ 
        { 0x0101, 0x8004 },    /* R257   - Control Interface */ 
        { 0x0110, 0x0000 },    /* R272   - Write Sequencer Ctrl (1) */ 
        { 0x0111, 0x0000 },    /* R273   - Write Sequencer Ctrl (2) */ 
@@ -292,7 +280,6 @@ static struct reg_default wm8994_defaults[] = {
        { 0x0209, 0x0000 },    /* R521   - Clocking (2) */ 
        { 0x0210, 0x0083 },    /* R528   - AIF1 Rate */ 
        { 0x0211, 0x0083 },    /* R529   - AIF2 Rate */ 
-       { 0x0212, 0x0000 },    /* R530   - Rate Status */ 
        { 0x0220, 0x0000 },    /* R544   - FLL1 Control (1) */ 
        { 0x0221, 0x0000 },    /* R545   - FLL1 Control (2) */ 
        { 0x0222, 0x0000 },    /* R546   - FLL1 Control (3) */ 
@@ -445,9 +432,6 @@ static struct reg_default wm8994_defaults[] = {
        { 0x070A, 0xA101 },    /* R1802  - GPIO 11 */ 
        { 0x0720, 0x0000 },    /* R1824  - Pull Control (1) */ 
        { 0x0721, 0x0156 },    /* R1825  - Pull Control (2) */ 
-       { 0x0730, 0x0000 },    /* R1840  - Interrupt Status 1 */ 
-       { 0x0731, 0x0000 },    /* R1841  - Interrupt Status 2 */ 
-       { 0x0732, 0x0000 },    /* R1842  - Interrupt Raw Status 2 */ 
        { 0x0738, 0x07FF },    /* R1848  - Interrupt Status 1 Mask */ 
        { 0x0739, 0xFFFF },    /* R1849  - Interrupt Status 2 Mask */ 
        { 0x0740, 0x0000 },    /* R1856  - Interrupt Control */ 
@@ -455,7 +439,6 @@ static struct reg_default wm8994_defaults[] = {
 };
 
 static struct reg_default wm8958_defaults[] = {
-       { 0x0000, 0x8958 },    /* R0     - Software Reset */ 
        { 0x0001, 0x0000 },    /* R1     - Power Management (1) */
        { 0x0002, 0x6000 },    /* R2     - Power Management (2) */
        { 0x0003, 0x0000 },    /* R3     - Power Management (3) */
@@ -970,6 +953,7 @@ static bool wm8994_readable_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8994_DC_SERVO_READBACK:
+       case WM8994_MICBIAS:
        case WM8994_WRITE_SEQUENCER_CTRL_1:
        case WM8994_WRITE_SEQUENCER_CTRL_2:
        case WM8994_AIF1_ADC2_LEFT_VOLUME:
index d95587cc794c81288f2211bf311f8823b9258321..04d5170ac14973520e23a56f283e8ea21c7c1f81 100644 (file)
@@ -40,6 +40,7 @@ extern void gru_wait_abort_proc(void *cb);
                        *((volatile unsigned long *)(p)) = v; /* force st.rel */        \
                } while (0)
 #elif defined(CONFIG_X86_64)
+#include <asm/cacheflush.h>
 #define __flush_cache(p)               clflush(p)
 #define gru_ordered_store_ulong(p, v)                                  \
                do {                                                    \
index 851b2f25ce0ee7120ca8b000807f87f1cef34853..c862cd4583cc93694747e191f5e3537e5767bfa5 100644 (file)
@@ -25,7 +25,6 @@
 #endif
 
 #if defined CONFIG_IA64
-#include <asm/system.h>
 #include <asm/sn/arch.h>       /* defines is_shub1() and is_shub2() */
 #define is_shub()      ia64_platform_is("sn2")
 #endif
index e5a3c7b6dedb471de5917873daee8f05a418c1a3..eed213a5c8cba8f53ae8bdba6e2f6525eedc9657 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "queue.h"
@@ -1080,6 +1079,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
        struct mmc_blk_request *brq = &mqrq->brq;
        struct request *req = mqrq->req;
        struct mmc_blk_data *md = mq->data;
+       bool do_data_tag;
 
        /*
         * Reliable writes are used to implement Forced Unit Access and
@@ -1155,6 +1155,16 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
        if (do_rel_wr)
                mmc_apply_rel_rw(brq, card, req);
 
+       /*
+        * Data tag is used only during writing meta data to speed
+        * up write and any subsequent read of this meta data
+        */
+       do_data_tag = (card->ext_csd.data_tag_unit_size) &&
+               (req->cmd_flags & REQ_META) &&
+               (rq_data_dir(req) == WRITE) &&
+               ((brq->data.blocks * brq->data.blksz) >=
+                card->ext_csd.data_tag_unit_size);
+
        /*
         * Pre-defined multi-block transfers are preferable to
         * open ended-ones (and necessary for reliable writes).
@@ -1173,13 +1183,13 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
         * We'll avoid using CMD23-bounded multiblock writes for
         * these, while retaining features like reliable writes.
         */
-
-       if ((md->flags & MMC_BLK_CMD23) &&
-           mmc_op_multi(brq->cmd.opcode) &&
-           (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
+       if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
+           (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
+            do_data_tag)) {
                brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
                brq->sbc.arg = brq->data.blocks |
-                       (do_rel_wr ? (1 << 31) : 0);
+                       (do_rel_wr ? (1 << 31) : 0) |
+                       (do_data_tag ? (1 << 29) : 0);
                brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
                brq->mrq.sbc = &brq->sbc;
        }
index 082202ae4a03cbc9fb5a4a32f3276e27bec98508..29de31e260dda56da18d0345f15a3886c6c1063a 100644 (file)
@@ -28,13 +28,17 @@ static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
-                       unsigned int irq, unsigned long flags)
+int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
 {
        size_t len = strlen(dev_name(host->parent)) + 4;
-       struct mmc_cd_gpio *cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
+       struct mmc_cd_gpio *cd;
+       int irq = gpio_to_irq(gpio);
        int ret;
 
+       if (irq < 0)
+               return irq;
+
+       cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
        if (!cd)
                return -ENOMEM;
 
@@ -45,7 +49,8 @@ int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
                goto egpioreq;
 
        ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
-                                  flags, cd->label, host);
+                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                                  cd->label, host);
        if (ret < 0)
                goto eirqreq;
 
index 132378b89d76a0072fe31b7f436975525d04e353..14f262e9246d7a853ad2e1d78ce561e1c51d58c2 100644 (file)
@@ -188,6 +188,12 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
        struct scatterlist *sg;
 #endif
 
+       if (mrq->sbc) {
+               pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n",
+                        mmc_hostname(host), mrq->sbc->opcode,
+                        mrq->sbc->arg, mrq->sbc->flags);
+       }
+
        pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
                 mmc_hostname(host), mrq->cmd->opcode,
                 mrq->cmd->arg, mrq->cmd->flags);
@@ -243,16 +249,17 @@ static void mmc_wait_done(struct mmc_request *mrq)
        complete(&mrq->completion);
 }
 
-static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
 {
        init_completion(&mrq->completion);
        mrq->done = mmc_wait_done;
        if (mmc_card_removed(host->card)) {
                mrq->cmd->error = -ENOMEDIUM;
                complete(&mrq->completion);
-               return;
+               return -ENOMEDIUM;
        }
        mmc_start_request(host, mrq);
+       return 0;
 }
 
 static void mmc_wait_for_req_done(struct mmc_host *host,
@@ -336,6 +343,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
                                    struct mmc_async_req *areq, int *error)
 {
        int err = 0;
+       int start_err = 0;
        struct mmc_async_req *data = host->areq;
 
        /* Prepare a new request */
@@ -345,30 +353,23 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
        if (host->areq) {
                mmc_wait_for_req_done(host, host->areq->mrq);
                err = host->areq->err_check(host->card, host->areq);
-               if (err) {
-                       /* post process the completed failed request */
-                       mmc_post_req(host, host->areq->mrq, 0);
-                       if (areq)
-                               /*
-                                * Cancel the new prepared request, because
-                                * it can't run until the failed
-                                * request has been properly handled.
-                                */
-                               mmc_post_req(host, areq->mrq, -EINVAL);
-
-                       host->areq = NULL;
-                       goto out;
-               }
        }
 
-       if (areq)
-               __mmc_start_req(host, areq->mrq);
+       if (!err && areq)
+               start_err = __mmc_start_req(host, areq->mrq);
 
        if (host->areq)
                mmc_post_req(host, host->areq->mrq, 0);
 
-       host->areq = areq;
- out:
+        /* Cancel a prepared request if it was not started. */
+       if ((err || start_err) && areq)
+                       mmc_post_req(host, areq->mrq, -EINVAL);
+
+       if (err)
+               host->areq = NULL;
+       else
+               host->areq = areq;
+
        if (error)
                *error = err;
        return data;
@@ -598,105 +599,6 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
 }
 EXPORT_SYMBOL(mmc_align_data_size);
 
-/**
- *     mmc_host_enable - enable a host.
- *     @host: mmc host to enable
- *
- *     Hosts that support power saving can use the 'enable' and 'disable'
- *     methods to exit and enter power saving states. For more information
- *     see comments for struct mmc_host_ops.
- */
-int mmc_host_enable(struct mmc_host *host)
-{
-       if (!(host->caps & MMC_CAP_DISABLE))
-               return 0;
-
-       if (host->en_dis_recurs)
-               return 0;
-
-       if (host->nesting_cnt++)
-               return 0;
-
-       cancel_delayed_work_sync(&host->disable);
-
-       if (host->enabled)
-               return 0;
-
-       if (host->ops->enable) {
-               int err;
-
-               host->en_dis_recurs = 1;
-               mmc_host_clk_hold(host);
-               err = host->ops->enable(host);
-               mmc_host_clk_release(host);
-               host->en_dis_recurs = 0;
-
-               if (err) {
-                       pr_debug("%s: enable error %d\n",
-                                mmc_hostname(host), err);
-                       return err;
-               }
-       }
-       host->enabled = 1;
-       return 0;
-}
-EXPORT_SYMBOL(mmc_host_enable);
-
-static int mmc_host_do_disable(struct mmc_host *host, int lazy)
-{
-       if (host->ops->disable) {
-               int err;
-
-               host->en_dis_recurs = 1;
-               mmc_host_clk_hold(host);
-               err = host->ops->disable(host, lazy);
-               mmc_host_clk_release(host);
-               host->en_dis_recurs = 0;
-
-               if (err < 0) {
-                       pr_debug("%s: disable error %d\n",
-                                mmc_hostname(host), err);
-                       return err;
-               }
-               if (err > 0) {
-                       unsigned long delay = msecs_to_jiffies(err);
-
-                       mmc_schedule_delayed_work(&host->disable, delay);
-               }
-       }
-       host->enabled = 0;
-       return 0;
-}
-
-/**
- *     mmc_host_disable - disable a host.
- *     @host: mmc host to disable
- *
- *     Hosts that support power saving can use the 'enable' and 'disable'
- *     methods to exit and enter power saving states. For more information
- *     see comments for struct mmc_host_ops.
- */
-int mmc_host_disable(struct mmc_host *host)
-{
-       int err;
-
-       if (!(host->caps & MMC_CAP_DISABLE))
-               return 0;
-
-       if (host->en_dis_recurs)
-               return 0;
-
-       if (--host->nesting_cnt)
-               return 0;
-
-       if (!host->enabled)
-               return 0;
-
-       err = mmc_host_do_disable(host, 0);
-       return err;
-}
-EXPORT_SYMBOL(mmc_host_disable);
-
 /**
  *     __mmc_claim_host - exclusively claim a host
  *     @host: mmc host to claim
@@ -735,8 +637,8 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
                wake_up(&host->wq);
        spin_unlock_irqrestore(&host->lock, flags);
        remove_wait_queue(&host->wq, &wait);
-       if (!stop)
-               mmc_host_enable(host);
+       if (host->ops->enable && !stop && host->claim_cnt == 1)
+               host->ops->enable(host);
        return stop;
 }
 
@@ -761,21 +663,28 @@ int mmc_try_claim_host(struct mmc_host *host)
                claimed_host = 1;
        }
        spin_unlock_irqrestore(&host->lock, flags);
+       if (host->ops->enable && claimed_host && host->claim_cnt == 1)
+               host->ops->enable(host);
        return claimed_host;
 }
 EXPORT_SYMBOL(mmc_try_claim_host);
 
 /**
- *     mmc_do_release_host - release a claimed host
+ *     mmc_release_host - release a host
  *     @host: mmc host to release
  *
- *     If you successfully claimed a host, this function will
- *     release it again.
+ *     Release a MMC host, allowing others to claim the host
+ *     for their operations.
  */
-void mmc_do_release_host(struct mmc_host *host)
+void mmc_release_host(struct mmc_host *host)
 {
        unsigned long flags;
 
+       WARN_ON(!host->claimed);
+
+       if (host->ops->disable && host->claim_cnt == 1)
+               host->ops->disable(host);
+
        spin_lock_irqsave(&host->lock, flags);
        if (--host->claim_cnt) {
                /* Release for nested claim */
@@ -787,67 +696,6 @@ void mmc_do_release_host(struct mmc_host *host)
                wake_up(&host->wq);
        }
 }
-EXPORT_SYMBOL(mmc_do_release_host);
-
-void mmc_host_deeper_disable(struct work_struct *work)
-{
-       struct mmc_host *host =
-               container_of(work, struct mmc_host, disable.work);
-
-       /* If the host is claimed then we do not want to disable it anymore */
-       if (!mmc_try_claim_host(host))
-               return;
-       mmc_host_do_disable(host, 1);
-       mmc_do_release_host(host);
-}
-
-/**
- *     mmc_host_lazy_disable - lazily disable a host.
- *     @host: mmc host to disable
- *
- *     Hosts that support power saving can use the 'enable' and 'disable'
- *     methods to exit and enter power saving states. For more information
- *     see comments for struct mmc_host_ops.
- */
-int mmc_host_lazy_disable(struct mmc_host *host)
-{
-       if (!(host->caps & MMC_CAP_DISABLE))
-               return 0;
-
-       if (host->en_dis_recurs)
-               return 0;
-
-       if (--host->nesting_cnt)
-               return 0;
-
-       if (!host->enabled)
-               return 0;
-
-       if (host->disable_delay) {
-               mmc_schedule_delayed_work(&host->disable,
-                               msecs_to_jiffies(host->disable_delay));
-               return 0;
-       } else
-               return mmc_host_do_disable(host, 1);
-}
-EXPORT_SYMBOL(mmc_host_lazy_disable);
-
-/**
- *     mmc_release_host - release a host
- *     @host: mmc host to release
- *
- *     Release a MMC host, allowing others to claim the host
- *     for their operations.
- */
-void mmc_release_host(struct mmc_host *host)
-{
-       WARN_ON(!host->claimed);
-
-       mmc_host_lazy_disable(host);
-
-       mmc_do_release_host(host);
-}
-
 EXPORT_SYMBOL(mmc_release_host);
 
 /*
@@ -2115,18 +1963,36 @@ int _mmc_detect_card_removed(struct mmc_host *host)
 int mmc_detect_card_removed(struct mmc_host *host)
 {
        struct mmc_card *card = host->card;
+       int ret;
 
        WARN_ON(!host->claimed);
+
+       if (!card)
+               return 1;
+
+       ret = mmc_card_removed(card);
        /*
         * The card will be considered unchanged unless we have been asked to
         * detect a change or host requires polling to provide card detection.
         */
-       if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL))
-               return mmc_card_removed(card);
+       if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) &&
+           !(host->caps2 & MMC_CAP2_DETECT_ON_ERR))
+               return ret;
 
        host->detect_change = 0;
+       if (!ret) {
+               ret = _mmc_detect_card_removed(host);
+               if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) {
+                       /*
+                        * Schedule a detect work as soon as possible to let a
+                        * rescan handle the card removal.
+                        */
+                       cancel_delayed_work(&host->detect);
+                       mmc_detect_change(host, 0);
+               }
+       }
 
-       return _mmc_detect_card_removed(host);
+       return ret;
 }
 EXPORT_SYMBOL(mmc_detect_card_removed);
 
@@ -2203,8 +2069,6 @@ void mmc_stop_host(struct mmc_host *host)
        spin_unlock_irqrestore(&host->lock, flags);
 #endif
 
-       if (host->caps & MMC_CAP_DISABLE)
-               cancel_delayed_work(&host->disable);
        cancel_delayed_work_sync(&host->detect);
        mmc_flush_scheduled_work();
 
@@ -2399,13 +2263,11 @@ int mmc_suspend_host(struct mmc_host *host)
 {
        int err = 0;
 
-       if (host->caps & MMC_CAP_DISABLE)
-               cancel_delayed_work(&host->disable);
        cancel_delayed_work(&host->detect);
        mmc_flush_scheduled_work();
        if (mmc_try_claim_host(host)) {
                err = mmc_cache_ctrl(host, 0);
-               mmc_do_release_host(host);
+               mmc_release_host(host);
        } else {
                err = -EBUSY;
        }
@@ -2426,7 +2288,7 @@ int mmc_suspend_host(struct mmc_host *host)
                        if (host->bus_ops->suspend) {
                                err = host->bus_ops->suspend(host);
                        }
-                       mmc_do_release_host(host);
+                       mmc_release_host(host);
 
                        if (err == -ENOSYS || !host->bus_ops->resume) {
                                /*
index c3704e293a7b30d52c9cc1893da88a0e4844131b..91c84c7a1829e8693c4e9dc652758512df22b4d6 100644 (file)
@@ -330,7 +330,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
        spin_lock_init(&host->lock);
        init_waitqueue_head(&host->wq);
        INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-       INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
 #ifdef CONFIG_PM
        host->pm_notify.notifier_call = mmc_pm_notify;
 #endif
index 08a7852ade448a126d56d0034ba9b0965206b7a5..f2ab9e5781265c29e1e62c6eaafb4618019532b9 100644 (file)
@@ -14,7 +14,6 @@
 
 int mmc_register_host_class(void);
 void mmc_unregister_host_class(void);
-void mmc_host_deeper_disable(struct work_struct *work);
 
 #endif
 
index 2b9ed1401dc439bf1dd29e4aa751f74e0175bc93..02914d609a91ab3d28577aed913702e119a695f6 100644 (file)
@@ -519,6 +519,20 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
                        ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
                        ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+
+               if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1)
+                       card->ext_csd.data_sector_size = 4096;
+               else
+                       card->ext_csd.data_sector_size = 512;
+
+               if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) &&
+                   (ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) {
+                       card->ext_csd.data_tag_unit_size =
+                       ((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) *
+                       (card->ext_csd.data_sector_size);
+               } else {
+                       card->ext_csd.data_tag_unit_size = 0;
+               }
        }
 
 out:
@@ -938,7 +952,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
         * bit.  This bit will be lost every time after a reset or power off.
         */
-       if (card->ext_csd.enhanced_area_en) {
+       if (card->ext_csd.enhanced_area_en ||
+           (card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) {
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                 EXT_CSD_ERASE_GROUP_DEF, 1,
                                 card->ext_csd.generic_cmd6_time);
@@ -1032,22 +1047,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                }
        }
 
-       /*
-        * Enable HPI feature (if supported)
-        */
-       if (card->ext_csd.hpi) {
-               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                       EXT_CSD_HPI_MGMT, 1, 0);
-               if (err && err != -EBADMSG)
-                       goto free_card;
-               if (err) {
-                       pr_warning("%s: Enabling HPI failed\n",
-                                  mmc_hostname(card->host));
-                       err = 0;
-               } else
-                       card->ext_csd.hpi_en = 1;
-       }
-
        /*
         * Compute bus speed.
         */
@@ -1097,9 +1096,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 4. execute tuning for HS200
                 */
                if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning)
+                   card->host->ops->execute_tuning) {
+                       mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
+                       mmc_host_clk_release(card->host);
+               }
                if (err) {
                        pr_warning("%s: tuning execution failed\n",
                                   mmc_hostname(card->host));
@@ -1218,6 +1220,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                }
        }
 
+       /*
+        * Enable HPI feature (if supported)
+        */
+       if (card->ext_csd.hpi) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                               EXT_CSD_HPI_MGMT, 1,
+                               card->ext_csd.generic_cmd6_time);
+               if (err && err != -EBADMSG)
+                       goto free_card;
+               if (err) {
+                       pr_warning("%s: Enabling HPI failed\n",
+                                  mmc_hostname(card->host));
+                       err = 0;
+               } else
+                       card->ext_csd.hpi_en = 1;
+       }
+
        /*
         * If cache size is higher than 0, this indicates
         * the existence of cache and it can be turned on.
index 4d41fa984c9344d007a1df43898f25a18c0a4e91..69370f494e054f7951d287bba8b1d570510dc33d 100644 (file)
@@ -553,18 +553,22 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
 {
        struct mmc_command cmd = {0};
        unsigned int opcode;
-       unsigned int flags;
        int err;
 
+       if (!card->ext_csd.hpi) {
+               pr_warning("%s: Card didn't support HPI command\n",
+                          mmc_hostname(card->host));
+               return -EINVAL;
+       }
+
        opcode = card->ext_csd.hpi_cmd;
        if (opcode == MMC_STOP_TRANSMISSION)
-               flags = MMC_RSP_R1 | MMC_CMD_AC;
+               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
        else if (opcode == MMC_SEND_STATUS)
-               flags = MMC_RSP_R1 | MMC_CMD_AC;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
        cmd.opcode = opcode;
        cmd.arg = card->rca << 16 | 1;
-       cmd.flags = flags;
        cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
 
        err = mmc_wait_for_cmd(card->host, &cmd, 0);
index ecbee9bf87b2ef00cf18f54ff6968fe4f2616adf..2bc06e7344db5970c754ab6cbf0a849830d8339f 100644 (file)
@@ -533,6 +533,31 @@ config MMC_DW_IDMAC
          Designware Mobile Storage IP block. This disables the external DMA
          interface.
 
+config MMC_DW_PLTFM
+       tristate "Synopsys Designware MCI Support as platform device"
+       depends on MMC_DW
+       default y
+       help
+         This selects the common helper functions support for Host Controller
+         Interface based platform driver. Please select this option if the IP
+         is present as a platform device. This is the common interface for the
+         Synopsys Designware IP.
+
+         If you have a controller with this interface, say Y or M here.
+
+         If unsure, say Y.
+
+config MMC_DW_PCI
+       tristate "Synopsys Designware MCI support on PCI bus"
+       depends on MMC_DW && PCI
+       help
+         This selects the PCI bus for the Synopsys Designware Mobile Storage IP.
+         Select this option if the IP is present on PCI platform.
+
+         If you have a controller with this interface, say Y or M here.
+
+         If unsure, say N.
+
 config MMC_SH_MMCIF
        tristate "SuperH Internal MMCIF support"
        depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE)
index 745f8fce251986278b408951fd1d5b4a12015893..3e7e26d0807346a82353544a0623086ce4249409 100644 (file)
@@ -39,6 +39,8 @@ obj-$(CONFIG_MMC_CB710)               += cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)    += via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)         += bfin_sdh.o
 obj-$(CONFIG_MMC_DW)           += dw_mmc.o
+obj-$(CONFIG_MMC_DW_PLTFM)     += dw_mmc-pltfm.o
+obj-$(CONFIG_MMC_DW_PCI)       += dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)     += sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)       += jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)       += vub300.o
index e4449a54ae8f9fc68c3d9f719fe3a09e3e028adf..9819dc09ce08d24f7bd2924fd35d786cc013b0ac 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
+#include <linux/types.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdio.h>
@@ -173,6 +174,7 @@ struct atmel_mci {
 
        struct atmel_mci_dma    dma;
        struct dma_chan         *data_chan;
+       struct dma_slave_config dma_conf;
 
        u32                     cmd_status;
        u32                     data_status;
@@ -863,16 +865,17 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
 
        if (data->flags & MMC_DATA_READ) {
                direction = DMA_FROM_DEVICE;
-               slave_dirn = DMA_DEV_TO_MEM;
+               host->dma_conf.direction = slave_dirn = DMA_DEV_TO_MEM;
        } else {
                direction = DMA_TO_DEVICE;
-               slave_dirn = DMA_MEM_TO_DEV;
+               host->dma_conf.direction = slave_dirn = DMA_MEM_TO_DEV;
        }
 
        sglen = dma_map_sg(chan->device->dev, data->sg,
                        data->sg_len, direction);
 
-       desc = chan->device->device_prep_slave_sg(chan,
+       dmaengine_slave_config(chan, &host->dma_conf);
+       desc = dmaengine_prep_slave_sg(chan,
                        data->sg, sglen, slave_dirn,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc)
@@ -1960,10 +1963,6 @@ static bool atmci_configure_dma(struct atmel_mci *host)
        if (pdata && find_slave_dev(pdata->dma_slave)) {
                dma_cap_mask_t mask;
 
-               setup_dma_addr(pdata->dma_slave,
-                              host->mapbase + ATMCI_TDR,
-                              host->mapbase + ATMCI_RDR);
-
                /* Try to grab a DMA channel */
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
@@ -1975,8 +1974,16 @@ static bool atmci_configure_dma(struct atmel_mci *host)
                return false;
        } else {
                dev_info(&host->pdev->dev,
-                                       "Using %s for DMA transfers\n",
+                                       "using %s for DMA transfers\n",
                                        dma_chan_name(host->dma.chan));
+
+               host->dma_conf.src_addr = host->mapbase + ATMCI_RDR;
+               host->dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               host->dma_conf.src_maxburst = 1;
+               host->dma_conf.dst_addr = host->mapbase + ATMCI_TDR;
+               host->dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               host->dma_conf.dst_maxburst = 1;
+               host->dma_conf.device_fc = false;
                return true;
        }
 }
index 64a8325a4a8af8f590204e1f38441128eab7e9bd..c1f3673ae1efa9df281bbb88687029af24309f29 100644 (file)
@@ -160,6 +160,16 @@ module_param(rw_threshold, uint, S_IRUGO);
 MODULE_PARM_DESC(rw_threshold,
                "Read/Write threshold. Default = 32");
 
+static unsigned poll_threshold = 128;
+module_param(poll_threshold, uint, S_IRUGO);
+MODULE_PARM_DESC(poll_threshold,
+                "Polling transaction size threshold. Default = 128");
+
+static unsigned poll_loopcount = 32;
+module_param(poll_loopcount, uint, S_IRUGO);
+MODULE_PARM_DESC(poll_loopcount,
+                "Maximum polling loop count. Default = 32");
+
 static unsigned __initdata use_dma = 1;
 module_param(use_dma, uint, 0);
 MODULE_PARM_DESC(use_dma, "Whether to use DMA or not. Default = 1");
@@ -193,6 +203,7 @@ struct mmc_davinci_host {
        bool use_dma;
        bool do_dma;
        bool sdio_int;
+       bool active_request;
 
        /* Scatterlist DMA uses one or more parameter RAM entries:
         * the main one (associated with rxdma or txdma) plus zero or
@@ -219,6 +230,7 @@ struct mmc_davinci_host {
 #endif
 };
 
+static irqreturn_t mmc_davinci_irq(int irq, void *dev_id);
 
 /* PIO only */
 static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host)
@@ -376,7 +388,20 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host,
 
        writel(cmd->arg, host->base + DAVINCI_MMCARGHL);
        writel(cmd_reg,  host->base + DAVINCI_MMCCMD);
-       writel(im_val, host->base + DAVINCI_MMCIM);
+
+       host->active_request = true;
+
+       if (!host->do_dma && host->bytes_left <= poll_threshold) {
+               u32 count = poll_loopcount;
+
+               while (host->active_request && count--) {
+                       mmc_davinci_irq(0, host);
+                       cpu_relax();
+               }
+       }
+
+       if (host->active_request)
+               writel(im_val, host->base + DAVINCI_MMCIM);
 }
 
 /*----------------------------------------------------------------------*/
@@ -915,6 +940,7 @@ mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data)
        if (!data->stop || (host->cmd && host->cmd->error)) {
                mmc_request_done(host->mmc, data->mrq);
                writel(0, host->base + DAVINCI_MMCIM);
+               host->active_request = false;
        } else
                mmc_davinci_start_command(host, data->stop);
 }
@@ -942,6 +968,7 @@ static void mmc_davinci_cmd_done(struct mmc_davinci_host *host,
                        cmd->mrq->cmd->retries = 0;
                mmc_request_done(host->mmc, cmd->mrq);
                writel(0, host->base + DAVINCI_MMCIM);
+               host->active_request = false;
        }
 }
 
@@ -1009,12 +1036,33 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
         * by read. So, it is not unbouned loop even in the case of
         * non-dma.
         */
-       while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) {
-               davinci_fifo_data_trans(host, rw_threshold);
-               status = readl(host->base + DAVINCI_MMCST0);
-               if (!status)
-                       break;
-               qstatus |= status;
+       if (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) {
+               unsigned long im_val;
+
+               /*
+                * If interrupts fire during the following loop, they will be
+                * handled by the handler, but the PIC will still buffer these.
+                * As a result, the handler will be called again to serve these
+                * needlessly. In order to avoid these spurious interrupts,
+                * keep interrupts masked during the loop.
+                */
+               im_val = readl(host->base + DAVINCI_MMCIM);
+               writel(0, host->base + DAVINCI_MMCIM);
+
+               do {
+                       davinci_fifo_data_trans(host, rw_threshold);
+                       status = readl(host->base + DAVINCI_MMCST0);
+                       qstatus |= status;
+               } while (host->bytes_left &&
+                        (status & (MMCST0_DXRDY | MMCST0_DRRDY)));
+
+               /*
+                * If an interrupt is pending, it is assumed it will fire when
+                * it is unmasked. This assumption is also taken when the MMCIM
+                * is first set. Otherwise, writing to MMCIM after reading the
+                * status is race-prone.
+                */
+               writel(im_val, host->base + DAVINCI_MMCIM);
        }
 
        if (qstatus & MMCST0_DATDNE) {
@@ -1418,17 +1466,14 @@ static int davinci_mmcsd_suspend(struct device *dev)
        struct mmc_davinci_host *host = platform_get_drvdata(pdev);
        int ret;
 
-       mmc_host_enable(host->mmc);
        ret = mmc_suspend_host(host->mmc);
        if (!ret) {
                writel(0, host->base + DAVINCI_MMCIM);
                mmc_davinci_reset_ctrl(host, 1);
-               mmc_host_disable(host->mmc);
                clk_disable(host->clk);
                host->suspended = 1;
        } else {
                host->suspended = 0;
-               mmc_host_disable(host->mmc);
        }
 
        return ret;
@@ -1444,7 +1489,6 @@ static int davinci_mmcsd_resume(struct device *dev)
                return 0;
 
        clk_enable(host->clk);
-       mmc_host_enable(host->mmc);
 
        mmc_davinci_reset_ctrl(host, 0);
        ret = mmc_resume_host(host->mmc);
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
new file mode 100644 (file)
index 0000000..dc0d25a
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Synopsys DesignWare Multimedia Card PCI Interface driver
+ *
+ * Copyright (C) 2012 Vayavya Labs Pvt. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/dw_mmc.h>
+#include "dw_mmc.h"
+
+#define PCI_BAR_NO 2
+#define COMPLETE_BAR 0
+#define SYNOPSYS_DW_MCI_VENDOR_ID 0x700
+#define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107
+/* Defining the Capabilities */
+#define DW_MCI_CAPABILITIES (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |\
+                               MMC_CAP_SD_HIGHSPEED | MMC_CAP_8_BIT_DATA |\
+                               MMC_CAP_SDIO_IRQ)
+
+static struct dw_mci_board pci_board_data = {
+       .num_slots                      = 1,
+       .caps                           = DW_MCI_CAPABILITIES,
+       .bus_hz                         = 33 * 1000 * 1000,
+       .detect_delay_ms                = 200,
+       .fifo_depth                     = 32,
+};
+
+static int __devinit dw_mci_pci_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *entries)
+{
+       struct dw_mci *host;
+       int ret;
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+       if (pci_request_regions(pdev, "dw_mmc_pci")) {
+               ret = -ENODEV;
+               goto err_disable_dev;
+       }
+
+       host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
+       if (!host) {
+               ret = -ENOMEM;
+               goto err_release;
+       }
+
+       host->irq = pdev->irq;
+       host->irq_flags = IRQF_SHARED;
+       host->dev = pdev->dev;
+       host->pdata = &pci_board_data;
+
+       host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR);
+       if (!host->regs) {
+               ret = -EIO;
+               goto err_unmap;
+       }
+
+       pci_set_drvdata(pdev, host);
+       ret = dw_mci_probe(host);
+       if (ret)
+               goto err_probe_failed;
+       return ret;
+
+err_probe_failed:
+       pci_iounmap(pdev, host->regs);
+err_unmap:
+       kfree(host);
+err_release:
+       pci_release_regions(pdev);
+err_disable_dev:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void __devexit dw_mci_pci_remove(struct pci_dev *pdev)
+{
+       struct dw_mci *host = pci_get_drvdata(pdev);
+
+       dw_mci_remove(host);
+       pci_set_drvdata(pdev, NULL);
+       pci_release_regions(pdev);
+       pci_iounmap(pdev, host->regs);
+       kfree(host);
+       pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dw_mci_pci_suspend(struct device *dev)
+{
+       int ret;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct dw_mci *host = pci_get_drvdata(pdev);
+
+       ret = dw_mci_suspend(host);
+       return ret;
+}
+
+static int dw_mci_pci_resume(struct device *dev)
+{
+       int ret;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct dw_mci *host = pci_get_drvdata(pdev);
+
+       ret = dw_mci_resume(host);
+       return ret;
+}
+#else
+#define dw_mci_pci_suspend     NULL
+#define dw_mci_pci_resume      NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume);
+
+static DEFINE_PCI_DEVICE_TABLE(dw_mci_pci_id) = {
+       { PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
+       {}
+};
+MODULE_DEVICE_TABLE(pci, dw_mci_pci_id);
+
+static struct pci_driver dw_mci_pci_driver = {
+       .name           = "dw_mmc_pci",
+       .id_table       = dw_mci_pci_id,
+       .probe          = dw_mci_pci_probe,
+       .remove         = dw_mci_pci_remove,
+       .driver         =       {
+               .pm =   &dw_mci_pci_pmops
+       },
+};
+
+static int __init dw_mci_init(void)
+{
+       return pci_register_driver(&dw_mci_pci_driver);
+}
+
+static void __exit dw_mci_exit(void)
+{
+       pci_unregister_driver(&dw_mci_pci_driver);
+}
+
+module_init(dw_mci_init);
+module_exit(dw_mci_exit);
+
+MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver");
+MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
new file mode 100644 (file)
index 0000000..92ec3eb
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Synopsys DesignWare Multimedia Card Interface driver
+ *
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2009, 2010 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/dw_mmc.h>
+#include "dw_mmc.h"
+
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
+{
+       struct dw_mci *host;
+       struct resource *regs;
+       int ret;
+
+       host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
+       if (!host)
+               return -ENOMEM;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs) {
+               ret = -ENXIO;
+               goto err_free;
+       }
+
+       host->irq = platform_get_irq(pdev, 0);
+       if (host->irq < 0) {
+               ret = host->irq;
+               goto err_free;
+       }
+
+       host->dev = pdev->dev;
+       host->irq_flags = 0;
+       host->pdata = pdev->dev.platform_data;
+       ret = -ENOMEM;
+       host->regs = ioremap(regs->start, resource_size(regs));
+       if (!host->regs)
+               goto err_free;
+       platform_set_drvdata(pdev, host);
+       ret = dw_mci_probe(host);
+       if (ret)
+               goto err_out;
+       return ret;
+err_out:
+       iounmap(host->regs);
+err_free:
+       kfree(host);
+       return ret;
+}
+
+static int __exit dw_mci_pltfm_remove(struct platform_device *pdev)
+{
+       struct dw_mci *host = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       dw_mci_remove(host);
+       iounmap(host->regs);
+       kfree(host);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+/*
+ * TODO: we should probably disable the clock to the card in the suspend path.
+ */
+static int dw_mci_pltfm_suspend(struct device *dev)
+{
+       int ret;
+       struct dw_mci *host = dev_get_drvdata(dev);
+
+       ret = dw_mci_suspend(host);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int dw_mci_pltfm_resume(struct device *dev)
+{
+       int ret;
+       struct dw_mci *host = dev_get_drvdata(dev);
+
+       ret = dw_mci_resume(host);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+#else
+#define dw_mci_pltfm_suspend   NULL
+#define dw_mci_pltfm_resume    NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume);
+
+static struct platform_driver dw_mci_pltfm_driver = {
+       .remove         = __exit_p(dw_mci_pltfm_remove),
+       .driver         = {
+               .name           = "dw_mmc",
+               .pm             = &dw_mci_pltfm_pmops,
+       },
+};
+
+static int __init dw_mci_init(void)
+{
+       return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe);
+}
+
+static void __exit dw_mci_exit(void)
+{
+       platform_driver_unregister(&dw_mci_pltfm_driver);
+}
+
+module_init(dw_mci_init);
+module_exit(dw_mci_exit);
+
+MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
+MODULE_AUTHOR("NXP Semiconductor VietNam");
+MODULE_AUTHOR("Imagination Technologies Ltd");
+MODULE_LICENSE("GPL v2");
index 8bec1c36b159159593bcad0263f0bca2787d4b92..bf3c9b456aaf1080d6db5163eacefb3e7805787a 100644 (file)
@@ -268,7 +268,7 @@ static void dw_mci_start_command(struct dw_mci *host,
                                 struct mmc_command *cmd, u32 cmd_flags)
 {
        host->cmd = cmd;
-       dev_vdbg(&host->pdev->dev,
+       dev_vdbg(&host->dev,
                 "start command: ARGR=0x%08x CMDR=0x%08x\n",
                 cmd->arg, cmd_flags);
 
@@ -295,15 +295,25 @@ static void dw_mci_stop_dma(struct dw_mci *host)
        }
 }
 
+static int dw_mci_get_dma_dir(struct mmc_data *data)
+{
+       if (data->flags & MMC_DATA_WRITE)
+               return DMA_TO_DEVICE;
+       else
+               return DMA_FROM_DEVICE;
+}
+
 #ifdef CONFIG_MMC_DW_IDMAC
 static void dw_mci_dma_cleanup(struct dw_mci *host)
 {
        struct mmc_data *data = host->data;
 
        if (data)
-               dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
-                            ((data->flags & MMC_DATA_WRITE)
-                             ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+               if (!data->host_cookie)
+                       dma_unmap_sg(&host->dev,
+                                    data->sg,
+                                    data->sg_len,
+                                    dw_mci_get_dma_dir(data));
 }
 
 static void dw_mci_idmac_stop_dma(struct dw_mci *host)
@@ -326,7 +336,7 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host)
 {
        struct mmc_data *data = host->data;
 
-       dev_vdbg(&host->pdev->dev, "DMA complete\n");
+       dev_vdbg(&host->dev, "DMA complete\n");
 
        host->dma_ops->cleanup(host);
 
@@ -428,17 +438,15 @@ static struct dw_mci_dma_ops dw_mci_idmac_ops = {
 };
 #endif /* CONFIG_MMC_DW_IDMAC */
 
-static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
+static int dw_mci_pre_dma_transfer(struct dw_mci *host,
+                                  struct mmc_data *data,
+                                  bool next)
 {
        struct scatterlist *sg;
-       unsigned int i, direction, sg_len;
-       u32 temp;
+       unsigned int i, sg_len;
 
-       host->using_dma = 0;
-
-       /* If we don't have a channel, we can't do DMA */
-       if (!host->use_dma)
-               return -ENODEV;
+       if (!next && data->host_cookie)
+               return data->host_cookie;
 
        /*
         * We don't do DMA on "complex" transfers, i.e. with
@@ -447,6 +455,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
         */
        if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
                return -EINVAL;
+
        if (data->blksz & 3)
                return -EINVAL;
 
@@ -455,17 +464,74 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
                        return -EINVAL;
        }
 
-       host->using_dma = 1;
+       sg_len = dma_map_sg(&host->dev,
+                           data->sg,
+                           data->sg_len,
+                           dw_mci_get_dma_dir(data));
+       if (sg_len == 0)
+               return -EINVAL;
 
-       if (data->flags & MMC_DATA_READ)
-               direction = DMA_FROM_DEVICE;
-       else
-               direction = DMA_TO_DEVICE;
+       if (next)
+               data->host_cookie = sg_len;
 
-       sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len,
-                           direction);
+       return sg_len;
+}
 
-       dev_vdbg(&host->pdev->dev,
+static void dw_mci_pre_req(struct mmc_host *mmc,
+                          struct mmc_request *mrq,
+                          bool is_first_req)
+{
+       struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct mmc_data *data = mrq->data;
+
+       if (!slot->host->use_dma || !data)
+               return;
+
+       if (data->host_cookie) {
+               data->host_cookie = 0;
+               return;
+       }
+
+       if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0)
+               data->host_cookie = 0;
+}
+
+static void dw_mci_post_req(struct mmc_host *mmc,
+                           struct mmc_request *mrq,
+                           int err)
+{
+       struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct mmc_data *data = mrq->data;
+
+       if (!slot->host->use_dma || !data)
+               return;
+
+       if (data->host_cookie)
+               dma_unmap_sg(&slot->host->dev,
+                            data->sg,
+                            data->sg_len,
+                            dw_mci_get_dma_dir(data));
+       data->host_cookie = 0;
+}
+
+static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
+{
+       int sg_len;
+       u32 temp;
+
+       host->using_dma = 0;
+
+       /* If we don't have a channel, we can't do DMA */
+       if (!host->use_dma)
+               return -ENODEV;
+
+       sg_len = dw_mci_pre_dma_transfer(host, data, 0);
+       if (sg_len < 0)
+               return sg_len;
+
+       host->using_dma = 1;
+
+       dev_vdbg(&host->dev,
                 "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
                 (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
                 sg_len);
@@ -579,8 +645,8 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
                             SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
 
                /* enable clock */
-               mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE |
-                          SDMMC_CLKEN_LOW_PWR);
+               mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE |
+                          SDMMC_CLKEN_LOW_PWR) << slot->id));
 
                /* inform CIU */
                mci_send_cmd(slot,
@@ -800,6 +866,8 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
 
 static const struct mmc_host_ops dw_mci_ops = {
        .request                = dw_mci_request,
+       .pre_req                = dw_mci_pre_req,
+       .post_req               = dw_mci_post_req,
        .set_ios                = dw_mci_set_ios,
        .get_ro                 = dw_mci_get_ro,
        .get_cd                 = dw_mci_get_cd,
@@ -821,12 +889,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
                slot = list_entry(host->queue.next,
                                  struct dw_mci_slot, queue_node);
                list_del(&slot->queue_node);
-               dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n",
+               dev_vdbg(&host->dev, "list not empty: %s is next\n",
                         mmc_hostname(slot->mmc));
                host->state = STATE_SENDING_CMD;
                dw_mci_start_request(host, slot);
        } else {
-               dev_vdbg(&host->pdev->dev, "list empty\n");
+               dev_vdbg(&host->dev, "list empty\n");
                host->state = STATE_IDLE;
        }
 
@@ -965,7 +1033,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                        data->bytes_xfered = 0;
                                        data->error = -ETIMEDOUT;
                                } else {
-                                       dev_err(&host->pdev->dev,
+                                       dev_err(&host->dev,
                                                "data FIFO error "
                                                "(status=%08x)\n",
                                                status);
@@ -1682,7 +1750,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
 
-       mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->pdev->dev);
+       mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->dev);
        if (!mmc)
                return -ENOMEM;
 
@@ -1720,13 +1788,11 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
-#ifdef CONFIG_MMC_DW_IDMAC
-       mmc->max_segs = host->ring_size;
-       mmc->max_blk_size = 65536;
-       mmc->max_blk_count = host->ring_size;
-       mmc->max_seg_size = 0x1000;
-       mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
-#else
+       if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY)
+               mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
+       else
+               mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
+
        if (host->pdata->blk_settings) {
                mmc->max_segs = host->pdata->blk_settings->max_segs;
                mmc->max_blk_size = host->pdata->blk_settings->max_blk_size;
@@ -1735,13 +1801,20 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->max_seg_size = host->pdata->blk_settings->max_seg_size;
        } else {
                /* Useful defaults if platform data is unset. */
+#ifdef CONFIG_MMC_DW_IDMAC
+               mmc->max_segs = host->ring_size;
+               mmc->max_blk_size = 65536;
+               mmc->max_blk_count = host->ring_size;
+               mmc->max_seg_size = 0x1000;
+               mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
+#else
                mmc->max_segs = 64;
                mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
                mmc->max_blk_count = 512;
                mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
                mmc->max_seg_size = mmc->max_req_size;
-       }
 #endif /* CONFIG_MMC_DW_IDMAC */
+       }
 
        host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
        if (IS_ERR(host->vmmc)) {
@@ -1789,10 +1862,10 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
 static void dw_mci_init_dma(struct dw_mci *host)
 {
        /* Alloc memory for sg translation */
-       host->sg_cpu = dma_alloc_coherent(&host->pdev->dev, PAGE_SIZE,
+       host->sg_cpu = dma_alloc_coherent(&host->dev, PAGE_SIZE,
                                          &host->sg_dma, GFP_KERNEL);
        if (!host->sg_cpu) {
-               dev_err(&host->pdev->dev, "%s: could not alloc DMA memory\n",
+               dev_err(&host->dev, "%s: could not alloc DMA memory\n",
                        __func__);
                goto no_dma;
        }
@@ -1800,7 +1873,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
        /* Determine which DMA interface to use */
 #ifdef CONFIG_MMC_DW_IDMAC
        host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(&host->pdev->dev, "Using internal DMA controller.\n");
+       dev_info(&host->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
@@ -1808,12 +1881,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
 
        if (host->dma_ops->init) {
                if (host->dma_ops->init(host)) {
-                       dev_err(&host->pdev->dev, "%s: Unable to initialize "
+                       dev_err(&host->dev, "%s: Unable to initialize "
                                "DMA Controller.\n", __func__);
                        goto no_dma;
                }
        } else {
-               dev_err(&host->pdev->dev, "DMA initialization not found.\n");
+               dev_err(&host->dev, "DMA initialization not found.\n");
                goto no_dma;
        }
 
@@ -1821,7 +1894,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
        return;
 
 no_dma:
-       dev_info(&host->pdev->dev, "Using PIO mode.\n");
+       dev_info(&host->dev, "Using PIO mode.\n");
        host->use_dma = 0;
        return;
 }
@@ -1847,61 +1920,37 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host)
        return false;
 }
 
-static int dw_mci_probe(struct platform_device *pdev)
+int dw_mci_probe(struct dw_mci *host)
 {
-       struct dw_mci *host;
-       struct resource *regs;
-       struct dw_mci_board *pdata;
-       int irq, ret, i, width;
+       int width, i, ret = 0;
        u32 fifo_size;
 
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs)
-               return -ENXIO;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
-
-       host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL);
-       if (!host)
-               return -ENOMEM;
-
-       host->pdev = pdev;
-       host->pdata = pdata = pdev->dev.platform_data;
-       if (!pdata || !pdata->init) {
-               dev_err(&pdev->dev,
+       if (!host->pdata || !host->pdata->init) {
+               dev_err(&host->dev,
                        "Platform data must supply init function\n");
-               ret = -ENODEV;
-               goto err_freehost;
+               return -ENODEV;
        }
 
-       if (!pdata->select_slot && pdata->num_slots > 1) {
-               dev_err(&pdev->dev,
+       if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
+               dev_err(&host->dev,
                        "Platform data must supply select_slot function\n");
-               ret = -ENODEV;
-               goto err_freehost;
+               return -ENODEV;
        }
 
-       if (!pdata->bus_hz) {
-               dev_err(&pdev->dev,
+       if (!host->pdata->bus_hz) {
+               dev_err(&host->dev,
                        "Platform data must supply bus speed\n");
-               ret = -ENODEV;
-               goto err_freehost;
+               return -ENODEV;
        }
 
-       host->bus_hz = pdata->bus_hz;
-       host->quirks = pdata->quirks;
+       host->bus_hz = host->pdata->bus_hz;
+       host->quirks = host->pdata->quirks;
 
        spin_lock_init(&host->lock);
        INIT_LIST_HEAD(&host->queue);
 
-       ret = -ENOMEM;
-       host->regs = ioremap(regs->start, resource_size(regs));
-       if (!host->regs)
-               goto err_freehost;
 
-       host->dma_ops = pdata->dma_ops;
+       host->dma_ops = host->pdata->dma_ops;
        dw_mci_init_dma(host);
 
        /*
@@ -1931,7 +1980,7 @@ static int dw_mci_probe(struct platform_device *pdev)
        }
 
        /* Reset all blocks */
-       if (!mci_wait_reset(&pdev->dev, host)) {
+       if (!mci_wait_reset(&host->dev, host)) {
                ret = -ENODEV;
                goto err_dmaunmap;
        }
@@ -1974,13 +2023,10 @@ static int dw_mci_probe(struct platform_device *pdev)
        if (!dw_mci_card_workqueue)
                goto err_dmaunmap;
        INIT_WORK(&host->card_work, dw_mci_work_routine_card);
-
-       ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host);
+       ret = request_irq(host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host);
        if (ret)
                goto err_workqueue;
 
-       platform_set_drvdata(pdev, host);
-
        if (host->pdata->num_slots)
                host->num_slots = host->pdata->num_slots;
        else
@@ -2000,7 +2046,7 @@ static int dw_mci_probe(struct platform_device *pdev)
         * Need to check the version-id and set data-offset for DATA register.
         */
        host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
-       dev_info(&pdev->dev, "Version ID is %04x\n", host->verid);
+       dev_info(&host->dev, "Version ID is %04x\n", host->verid);
 
        if (host->verid < DW_MMC_240A)
                host->data_offset = DATA_OFFSET;
@@ -2017,12 +2063,12 @@ static int dw_mci_probe(struct platform_device *pdev)
                   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
        mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
 
-       dev_info(&pdev->dev, "DW MMC controller at irq %d, "
+       dev_info(&host->dev, "DW MMC controller at irq %d, "
                 "%d bit host data width, "
                 "%u deep fifo\n",
-                irq, width, fifo_size);
+                host->irq, width, fifo_size);
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
-               dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n");
+               dev_info(&host->dev, "Internal DMAC interrupt fix enabled.\n");
 
        return 0;
 
@@ -2033,7 +2079,7 @@ err_init_slot:
                        dw_mci_cleanup_slot(host->slot[i], i);
                i--;
        }
-       free_irq(irq, host);
+       free_irq(host->irq, host);
 
 err_workqueue:
        destroy_workqueue(dw_mci_card_workqueue);
@@ -2041,33 +2087,26 @@ err_workqueue:
 err_dmaunmap:
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
-       dma_free_coherent(&host->pdev->dev, PAGE_SIZE,
+       dma_free_coherent(&host->dev, PAGE_SIZE,
                          host->sg_cpu, host->sg_dma);
-       iounmap(host->regs);
 
        if (host->vmmc) {
                regulator_disable(host->vmmc);
                regulator_put(host->vmmc);
        }
-
-
-err_freehost:
-       kfree(host);
        return ret;
 }
+EXPORT_SYMBOL(dw_mci_probe);
 
-static int __exit dw_mci_remove(struct platform_device *pdev)
+void dw_mci_remove(struct dw_mci *host)
 {
-       struct dw_mci *host = platform_get_drvdata(pdev);
        int i;
 
        mci_writel(host, RINTSTS, 0xFFFFFFFF);
        mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
 
-       platform_set_drvdata(pdev, NULL);
-
        for (i = 0; i < host->num_slots; i++) {
-               dev_dbg(&pdev->dev, "remove slot %d\n", i);
+               dev_dbg(&host->dev, "remove slot %d\n", i);
                if (host->slot[i])
                        dw_mci_cleanup_slot(host->slot[i], i);
        }
@@ -2076,9 +2115,9 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
        mci_writel(host, CLKENA, 0);
        mci_writel(host, CLKSRC, 0);
 
-       free_irq(platform_get_irq(pdev, 0), host);
+       free_irq(host->irq, host);
        destroy_workqueue(dw_mci_card_workqueue);
-       dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+       dma_free_coherent(&host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
 
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
@@ -2088,20 +2127,18 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
                regulator_put(host->vmmc);
        }
 
-       iounmap(host->regs);
-
-       kfree(host);
-       return 0;
 }
+EXPORT_SYMBOL(dw_mci_remove);
+
+
 
 #ifdef CONFIG_PM_SLEEP
 /*
  * TODO: we should probably disable the clock to the card in the suspend path.
  */
-static int dw_mci_suspend(struct device *dev)
+int dw_mci_suspend(struct dw_mci *host)
 {
-       int i, ret;
-       struct dw_mci *host = dev_get_drvdata(dev);
+       int i, ret = 0;
 
        for (i = 0; i < host->num_slots; i++) {
                struct dw_mci_slot *slot = host->slot[i];
@@ -2123,11 +2160,11 @@ static int dw_mci_suspend(struct device *dev)
 
        return 0;
 }
+EXPORT_SYMBOL(dw_mci_suspend);
 
-static int dw_mci_resume(struct device *dev)
+int dw_mci_resume(struct dw_mci *host)
 {
        int i, ret;
-       struct dw_mci *host = dev_get_drvdata(dev);
 
        if (host->vmmc)
                regulator_enable(host->vmmc);
@@ -2135,7 +2172,7 @@ static int dw_mci_resume(struct device *dev)
        if (host->dma_ops->init)
                host->dma_ops->init(host);
 
-       if (!mci_wait_reset(dev, host)) {
+       if (!mci_wait_reset(&host->dev, host)) {
                ret = -ENODEV;
                return ret;
        }
@@ -2157,32 +2194,19 @@ static int dw_mci_resume(struct device *dev)
                if (ret < 0)
                        return ret;
        }
-
        return 0;
 }
-#else
-#define dw_mci_suspend NULL
-#define dw_mci_resume  NULL
+EXPORT_SYMBOL(dw_mci_resume);
 #endif /* CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(dw_mci_pmops, dw_mci_suspend, dw_mci_resume);
-
-static struct platform_driver dw_mci_driver = {
-       .remove         = __exit_p(dw_mci_remove),
-       .driver         = {
-               .name           = "dw_mmc",
-               .pm             = &dw_mci_pmops,
-       },
-};
-
 static int __init dw_mci_init(void)
 {
-       return platform_driver_probe(&dw_mci_driver, dw_mci_probe);
+       printk(KERN_INFO "Synopsys Designware Multimedia Card Interface Driver");
+       return 0;
 }
 
 static void __exit dw_mci_exit(void)
 {
-       platform_driver_unregister(&dw_mci_driver);
 }
 
 module_init(dw_mci_init);
index df392a1143f279d75e798a89e37c4e13356f8291..15c27e17c23fad303e83368a6d2f8fac93ae9fe2 100644 (file)
        (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value))
 #endif
 
+extern int dw_mci_probe(struct dw_mci *host);
+extern void dw_mci_remove(struct dw_mci *host);
+#ifdef CONFIG_PM
+extern int dw_mci_suspend(struct dw_mci *host);
+extern int dw_mci_resume(struct dw_mci *host);
+#endif
+
 #endif /* _DW_MMC_H_ */
index 983e244eca769fcbd4be56b90780ff7c0156b84f..032b84791a16fecc10a7da9a9bae4f460cc9e1b9 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/amba/mmci.h>
 #include <linux/pm_runtime.h>
+#include <linux/types.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -400,6 +401,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
                .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
                .src_maxburst = variant->fifohalfsize >> 2, /* # of words */
                .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
+               .device_fc = false,
        };
        struct dma_chan *chan;
        struct dma_device *device;
@@ -441,7 +443,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
                return -EINVAL;
 
        dmaengine_slave_config(chan, &conf);
-       desc = device->device_prep_slave_sg(chan, data->sg, nr_sg,
+       desc = dmaengine_prep_slave_sg(chan, data->sg, nr_sg,
                                            conf.direction, DMA_CTRL_ACK);
        if (!desc)
                goto unmap_exit;
index 4184b7946bbf34fd459c671a921ae6baf659e4d2..b2058b4323209ba2a1a97aeabd21654655f02c0a 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/dmaengine.h>
+#include <linux/types.h>
 
 #include <asm/dma.h>
 #include <asm/irq.h>
@@ -254,7 +255,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
        if (nents != data->sg_len)
                return -EINVAL;
 
-       host->desc = host->dma->device->device_prep_slave_sg(host->dma,
+       host->desc = dmaengine_prep_slave_sg(host->dma,
                data->sg, data->sg_len, slave_dirn,
                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
@@ -267,6 +268,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
        wmb();
 
        dmaengine_submit(host->desc);
+       dma_async_issue_pending(host->dma);
 
        return 0;
 }
@@ -710,6 +712,7 @@ static int mxcmci_setup_dma(struct mmc_host *mmc)
        config->src_addr_width = 4;
        config->dst_maxburst = host->burstlen;
        config->src_maxburst = host->burstlen;
+       config->device_fc = false;
 
        return dmaengine_slave_config(host->dma, config);
 }
index 382c835d217cf23372594b230dcd7923971288d5..65f36cf2ff334bf0059ddd57401e5b70c19566e5 100644 (file)
@@ -324,7 +324,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
                sg_len = SSP_PIO_NUM;
        }
 
-       desc = host->dmach->device->device_prep_slave_sg(host->dmach,
+       desc = dmaengine_prep_slave_sg(host->dmach,
                                sgl, sg_len, host->slave_dirn, append);
        if (desc) {
                desc->callback = mxs_mmc_dma_irq_callback;
index fd0c661bbad38a7152a37955146ff6068d4d7137..47adb161d3adfd98e4c14279d04f4015d7283d2a 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/platform_device.h>
 #include <linux/timer.h>
 #include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/core.h>
 #include <linux/mmc/mmc.h>
 #define SOFTRESET              (1 << 1)
 #define RESETDONE              (1 << 0)
 
-/*
- * FIXME: Most likely all the data using these _DEVID defines should come
- * from the platform_data, or implemented in controller and slot specific
- * functions.
- */
-#define OMAP_MMC1_DEVID                0
-#define OMAP_MMC2_DEVID                1
-#define OMAP_MMC3_DEVID                2
-#define OMAP_MMC4_DEVID                3
-#define OMAP_MMC5_DEVID                4
-
 #define MMC_AUTOSUSPEND_DELAY  100
 #define MMC_TIMEOUT_MS         20
 #define OMAP_MMC_MIN_CLOCK     400000
@@ -164,7 +156,6 @@ struct omap_hsmmc_host {
        void    __iomem         *base;
        resource_size_t         mapbase;
        spinlock_t              irq_lock; /* Prevent races with irq handler */
-       unsigned int            id;
        unsigned int            dma_len;
        unsigned int            dma_sg_idx;
        unsigned char           bus_mode;
@@ -179,7 +170,6 @@ struct omap_hsmmc_host {
        int                     got_dbclk;
        int                     response_busy;
        int                     context_loss;
-       int                     dpm_state;
        int                     vdd;
        int                     protect_card;
        int                     reqs_blocked;
@@ -241,28 +231,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
 
 #ifdef CONFIG_REGULATOR
 
-static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on,
-                                 int vdd)
-{
-       struct omap_hsmmc_host *host =
-               platform_get_drvdata(to_platform_device(dev));
-       int ret;
-
-       if (mmc_slot(host).before_set_reg)
-               mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);
-
-       if (power_on)
-               ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
-       else
-               ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0);
-
-       if (mmc_slot(host).after_set_reg)
-               mmc_slot(host).after_set_reg(dev, slot, power_on, vdd);
-
-       return ret;
-}
-
-static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on,
+static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
                                   int vdd)
 {
        struct omap_hsmmc_host *host =
@@ -275,6 +244,13 @@ static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on,
         */
        if (!host->vcc)
                return 0;
+       /*
+        * With DT, never turn OFF the regulator. This is because
+        * the pbias cell programming support is still missing when
+        * booting with Device tree
+        */
+       if (of_have_populated_dt() && !vdd)
+               return 0;
 
        if (mmc_slot(host).before_set_reg)
                mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);
@@ -318,106 +294,16 @@ static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on,
        return ret;
 }
 
-static int omap_hsmmc_4_set_power(struct device *dev, int slot, int power_on,
-                                       int vdd)
-{
-       return 0;
-}
-
-static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
-                                 int vdd, int cardsleep)
-{
-       struct omap_hsmmc_host *host =
-               platform_get_drvdata(to_platform_device(dev));
-       int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
-
-       return regulator_set_mode(host->vcc, mode);
-}
-
-static int omap_hsmmc_235_set_sleep(struct device *dev, int slot, int sleep,
-                                  int vdd, int cardsleep)
-{
-       struct omap_hsmmc_host *host =
-               platform_get_drvdata(to_platform_device(dev));
-       int err, mode;
-
-       /*
-        * If we don't see a Vcc regulator, assume it's a fixed
-        * voltage always-on regulator.
-        */
-       if (!host->vcc)
-               return 0;
-
-       mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
-
-       if (!host->vcc_aux)
-               return regulator_set_mode(host->vcc, mode);
-
-       if (cardsleep) {
-               /* VCC can be turned off if card is asleep */
-               if (sleep)
-                       err = mmc_regulator_set_ocr(host->mmc, host->vcc, 0);
-               else
-                       err = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
-       } else
-               err = regulator_set_mode(host->vcc, mode);
-       if (err)
-               return err;
-
-       if (!mmc_slot(host).vcc_aux_disable_is_sleep)
-               return regulator_set_mode(host->vcc_aux, mode);
-
-       if (sleep)
-               return regulator_disable(host->vcc_aux);
-       else
-               return regulator_enable(host->vcc_aux);
-}
-
-static int omap_hsmmc_4_set_sleep(struct device *dev, int slot, int sleep,
-                                       int vdd, int cardsleep)
-{
-       return 0;
-}
-
 static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 {
        struct regulator *reg;
-       int ret = 0;
        int ocr_value = 0;
 
-       switch (host->id) {
-       case OMAP_MMC1_DEVID:
-               /* On-chip level shifting via PBIAS0/PBIAS1 */
-               mmc_slot(host).set_power = omap_hsmmc_1_set_power;
-               mmc_slot(host).set_sleep = omap_hsmmc_1_set_sleep;
-               break;
-       case OMAP_MMC2_DEVID:
-       case OMAP_MMC3_DEVID:
-       case OMAP_MMC5_DEVID:
-               /* Off-chip level shifting, or none */
-               mmc_slot(host).set_power = omap_hsmmc_235_set_power;
-               mmc_slot(host).set_sleep = omap_hsmmc_235_set_sleep;
-               break;
-       case OMAP_MMC4_DEVID:
-               mmc_slot(host).set_power = omap_hsmmc_4_set_power;
-               mmc_slot(host).set_sleep = omap_hsmmc_4_set_sleep;
-       default:
-               pr_err("MMC%d configuration not supported!\n", host->id);
-               return -EINVAL;
-       }
+       mmc_slot(host).set_power = omap_hsmmc_set_power;
 
        reg = regulator_get(host->dev, "vmmc");
        if (IS_ERR(reg)) {
                dev_dbg(host->dev, "vmmc regulator missing\n");
-               /*
-               * HACK: until fixed.c regulator is usable,
-               * we don't require a main regulator
-               * for MMC2 or MMC3
-               */
-               if (host->id == OMAP_MMC1_DEVID) {
-                       ret = PTR_ERR(reg);
-                       goto err;
-               }
        } else {
                host->vcc = reg;
                ocr_value = mmc_regulator_get_ocrmask(reg);
@@ -425,8 +311,8 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
                        mmc_slot(host).ocr_mask = ocr_value;
                } else {
                        if (!(mmc_slot(host).ocr_mask & ocr_value)) {
-                               pr_err("MMC%d ocrmask %x is not supported\n",
-                                       host->id, mmc_slot(host).ocr_mask);
+                               dev_err(host->dev, "ocrmask %x is not supported\n",
+                                       mmc_slot(host).ocr_mask);
                                mmc_slot(host).ocr_mask = 0;
                                return -EINVAL;
                        }
@@ -459,11 +345,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        }
 
        return 0;
-
-err:
-       mmc_slot(host).set_power = NULL;
-       mmc_slot(host).set_sleep = NULL;
-       return ret;
 }
 
 static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host)
@@ -471,7 +352,6 @@ static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host)
        regulator_put(host->vcc);
        regulator_put(host->vcc_aux);
        mmc_slot(host).set_power = NULL;
-       mmc_slot(host).set_sleep = NULL;
 }
 
 static inline int omap_hsmmc_have_reg(void)
@@ -710,7 +590,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
        OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
                        OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
 
-       if (host->id == OMAP_MMC1_DEVID) {
+       if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
                if (host->power_mode != MMC_POWER_OFF &&
                    (1 << ios->vdd) <= MMC_VDD_23_24)
                        hctl = SDVS18;
@@ -1261,14 +1141,14 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
        host->reqs_blocked = 0;
        if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) {
                if (host->protect_card) {
-                       pr_info("%s: cover is closed, "
+                       dev_info(host->dev, "%s: cover is closed, "
                                         "card is now accessible\n",
                                         mmc_hostname(host->mmc));
                        host->protect_card = 0;
                }
        } else {
                if (!host->protect_card) {
-                       pr_info("%s: cover is open, "
+                       dev_info(host->dev, "%s: cover is open, "
                                         "card is now inaccessible\n",
                                         mmc_hostname(host->mmc));
                        host->protect_card = 1;
@@ -1405,7 +1285,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
 
        if (!next && data->host_cookie &&
            data->host_cookie != host->next_data.cookie) {
-               pr_warning("[%s] invalid cookie: data->host_cookie %d"
+               dev_warn(host->dev, "[%s] invalid cookie: data->host_cookie %d"
                       " host->next_data.cookie %d\n",
                       __func__, data->host_cookie, host->next_data.cookie);
                data->host_cookie = 0;
@@ -1663,7 +1543,13 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                 * of external transceiver; but they all handle 1.8V.
                 */
                if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
-                       (ios->vdd == DUAL_VOLT_OCR_BIT)) {
+                       (ios->vdd == DUAL_VOLT_OCR_BIT) &&
+                       /*
+                        * With pbias cell programming missing, this
+                        * can't be allowed when booting with device
+                        * tree.
+                        */
+                       (!of_have_populated_dt())) {
                                /*
                                 * The mmc_select_voltage fn of the core does
                                 * not seem to set the power_mode to
@@ -1748,7 +1634,7 @@ static int omap_hsmmc_enable_fclk(struct mmc_host *mmc)
        return 0;
 }
 
-static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, int lazy)
+static int omap_hsmmc_disable_fclk(struct mmc_host *mmc)
 {
        struct omap_hsmmc_host *host = mmc_priv(mmc);
 
@@ -1782,15 +1668,8 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
        if (host->pdata->get_context_loss_count)
                context_loss = host->pdata->get_context_loss_count(host->dev);
 
-       seq_printf(s, "mmc%d:\n"
-                       " enabled:\t%d\n"
-                       " dpm_state:\t%d\n"
-                       " nesting_cnt:\t%d\n"
-                       " ctx_loss:\t%d:%d\n"
-                       "\nregs:\n",
-                       mmc->index, mmc->enabled ? 1 : 0,
-                       host->dpm_state, mmc->nesting_cnt,
-                       host->context_loss, context_loss);
+       seq_printf(s, "mmc%d:\n ctx_loss:\t%d:%d\n\nregs:\n",
+                       mmc->index, host->context_loss, context_loss);
 
        if (host->suspended) {
                seq_printf(s, "host suspended, can't read registers\n");
@@ -1847,6 +1726,65 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 
 #endif
 
+#ifdef CONFIG_OF
+static u16 omap4_reg_offset = 0x100;
+
+static const struct of_device_id omap_mmc_of_match[] = {
+       {
+               .compatible = "ti,omap2-hsmmc",
+       },
+       {
+               .compatible = "ti,omap3-hsmmc",
+       },
+       {
+               .compatible = "ti,omap4-hsmmc",
+               .data = &omap4_reg_offset,
+       },
+       {},
+}
+MODULE_DEVICE_TABLE(of, omap_mmc_of_match);
+
+static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+{
+       struct omap_mmc_platform_data *pdata;
+       struct device_node *np = dev->of_node;
+       u32 bus_width;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL; /* out of memory */
+
+       if (of_find_property(np, "ti,dual-volt", NULL))
+               pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
+
+       /* This driver only supports 1 slot */
+       pdata->nr_slots = 1;
+       pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
+       pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
+
+       if (of_find_property(np, "ti,non-removable", NULL)) {
+               pdata->slots[0].nonremovable = true;
+               pdata->slots[0].no_regulator_off_init = true;
+       }
+       of_property_read_u32(np, "ti,bus-width", &bus_width);
+       if (bus_width == 4)
+               pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA;
+       else if (bus_width == 8)
+               pdata->slots[0].caps |= MMC_CAP_8_BIT_DATA;
+
+       if (of_find_property(np, "ti,needs-special-reset", NULL))
+               pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
+       return pdata;
+}
+#else
+static inline struct omap_mmc_platform_data
+                       *of_get_hsmmc_pdata(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int __init omap_hsmmc_probe(struct platform_device *pdev)
 {
        struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
@@ -1854,6 +1792,16 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        struct omap_hsmmc_host *host = NULL;
        struct resource *res;
        int ret, irq;
+       const struct of_device_id *match;
+
+       match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
+       if (match) {
+               pdata = of_get_hsmmc_pdata(&pdev->dev);
+               if (match->data) {
+                       u16 *offsetp = match->data;
+                       pdata->reg_offset = *offsetp;
+               }
+       }
 
        if (pdata == NULL) {
                dev_err(&pdev->dev, "Platform Data is missing\n");
@@ -1894,7 +1842,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        host->dev->dma_mask = &pdata->dma_mask;
        host->dma_ch    = -1;
        host->irq       = irq;
-       host->id        = pdev->id;
        host->slot_id   = 0;
        host->mapbase   = res->start;
        host->base      = ioremap(host->mapbase, SZ_4K);
@@ -1912,8 +1859,12 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        if (mmc_slot(host).vcc_aux_disable_is_sleep)
                mmc_slot(host).no_off = 1;
 
-       mmc->f_min      = OMAP_MMC_MIN_CLOCK;
-       mmc->f_max      = OMAP_MMC_MAX_CLOCK;
+       mmc->f_min = OMAP_MMC_MIN_CLOCK;
+
+       if (pdata->max_freq > 0)
+               mmc->f_max = pdata->max_freq;
+       else
+               mmc->f_max = OMAP_MMC_MAX_CLOCK;
 
        spin_lock_init(&host->irq_lock);
 
@@ -1926,7 +1877,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 
        omap_hsmmc_context_save(host);
 
-       mmc->caps |= MMC_CAP_DISABLE;
        if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
                dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
                mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
@@ -1977,32 +1927,19 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 
        omap_hsmmc_conf_bus_power(host);
 
-       /* Select DMA lines */
-       switch (host->id) {
-       case OMAP_MMC1_DEVID:
-               host->dma_line_tx = OMAP24XX_DMA_MMC1_TX;
-               host->dma_line_rx = OMAP24XX_DMA_MMC1_RX;
-               break;
-       case OMAP_MMC2_DEVID:
-               host->dma_line_tx = OMAP24XX_DMA_MMC2_TX;
-               host->dma_line_rx = OMAP24XX_DMA_MMC2_RX;
-               break;
-       case OMAP_MMC3_DEVID:
-               host->dma_line_tx = OMAP34XX_DMA_MMC3_TX;
-               host->dma_line_rx = OMAP34XX_DMA_MMC3_RX;
-               break;
-       case OMAP_MMC4_DEVID:
-               host->dma_line_tx = OMAP44XX_DMA_MMC4_TX;
-               host->dma_line_rx = OMAP44XX_DMA_MMC4_RX;
-               break;
-       case OMAP_MMC5_DEVID:
-               host->dma_line_tx = OMAP44XX_DMA_MMC5_TX;
-               host->dma_line_rx = OMAP44XX_DMA_MMC5_RX;
-               break;
-       default:
-               dev_err(mmc_dev(host->mmc), "Invalid MMC id\n");
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+       if (!res) {
+               dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
+               goto err_irq;
+       }
+       host->dma_line_tx = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+       if (!res) {
+               dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
                goto err_irq;
        }
+       host->dma_line_rx = res->start;
 
        /* Request IRQ for MMC operations */
        ret = request_irq(host->irq, omap_hsmmc_irq, 0,
@@ -2083,6 +2020,7 @@ err_irq_cd_init:
 err_irq:
        pm_runtime_mark_last_busy(host->dev);
        pm_runtime_put_autosuspend(host->dev);
+       pm_runtime_disable(host->dev);
        clk_put(host->fclk);
        if (host->got_dbclk) {
                clk_disable(host->dbclk);
@@ -2269,6 +2207,7 @@ static struct platform_driver omap_hsmmc_driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
                .pm = &omap_hsmmc_dev_pm_ops,
+               .of_match_table = of_match_ptr(omap_mmc_of_match),
        },
 };
 
index 5d876ff86f377b5ec5b1a77a6cfcafc1ffca59e3..f8eb1fb0c9219283c9624f3f0a8adde251bcd5e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Freescale eSDHC controller driver.
  *
- * Copyright (c) 2007, 2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc.
  * Copyright (c) 2009 MontaVista Software, Inc.
  *
  * Authors: Xiaobo Xie <X.Xie@freescale.com>
@@ -14,6 +14,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
@@ -114,6 +115,34 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
        return pltfm_host->clock / 256 / 16;
 }
 
+static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+       /* Workaround to reduce the clock frequency for p1010 esdhc */
+       if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
+               if (clock > 20000000)
+                       clock -= 5000000;
+               if (clock > 40000000)
+                       clock -= 5000000;
+       }
+
+       /* Set the clock */
+       esdhc_set_clock(host, clock);
+}
+
+#ifdef CONFIG_PM
+static u32 esdhc_proctl;
+static void esdhc_of_suspend(struct sdhci_host *host)
+{
+       esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+}
+
+static void esdhc_of_resume(struct sdhci_host *host)
+{
+       esdhc_of_enable_dma(host);
+       sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+}
+#endif
+
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = sdhci_be32bs_readl,
        .read_w = esdhc_readw,
@@ -121,10 +150,14 @@ static struct sdhci_ops sdhci_esdhc_ops = {
        .write_l = sdhci_be32bs_writel,
        .write_w = esdhc_writew,
        .write_b = esdhc_writeb,
-       .set_clock = esdhc_set_clock,
+       .set_clock = esdhc_of_set_clock,
        .enable_dma = esdhc_of_enable_dma,
        .get_max_clock = esdhc_of_get_max_clock,
        .get_min_clock = esdhc_of_get_min_clock,
+#ifdef CONFIG_PM
+       .platform_suspend = esdhc_of_suspend,
+       .platform_resume = esdhc_of_resume,
+#endif
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
index 6ebdc4010e7ccb46e6f1052357fcdaca5dc3ecc9..fbbebe251e016cf8b24906aa6a0b4ad31f64cd40 100644 (file)
 
 #include "sdhci.h"
 
+/*
+ * PCI device IDs
+ */
+#define PCI_DEVICE_ID_INTEL_PCH_SDIO0  0x8809
+#define PCI_DEVICE_ID_INTEL_PCH_SDIO1  0x880a
+
 /*
  * PCI registers
  */
@@ -47,6 +53,7 @@ struct sdhci_pci_slot;
 
 struct sdhci_pci_fixes {
        unsigned int            quirks;
+       unsigned int            quirks2;
        bool                    allow_runtime_pm;
 
        int                     (*probe) (struct sdhci_pci_chip *);
@@ -73,6 +80,7 @@ struct sdhci_pci_chip {
        struct pci_dev          *pdev;
 
        unsigned int            quirks;
+       unsigned int            quirks2;
        bool                    allow_runtime_pm;
        const struct sdhci_pci_fixes *fixes;
 
@@ -172,6 +180,12 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
        return 0;
 }
 
+static int pch_hc_probe_slot(struct sdhci_pci_slot *slot)
+{
+       slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+       return 0;
+}
+
 #ifdef CONFIG_PM_RUNTIME
 
 static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id)
@@ -244,7 +258,8 @@ static inline void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot)
 static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;
-       slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC;
+       slot->host->mmc->caps2 |= MMC_CAP2_BOOTPART_NOACC |
+                                 MMC_CAP2_HC_ERASE_SZ;
        return 0;
 }
 
@@ -271,6 +286,7 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
        .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+       .quirks2        = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
        .allow_runtime_pm = true,
        .probe_slot     = mfd_sdio_probe_slot,
 };
@@ -281,6 +297,11 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
        .probe_slot     = mfd_emmc_probe_slot,
 };
 
+static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
+       .quirks         = SDHCI_QUIRK_BROKEN_ADMA,
+       .probe_slot     = pch_hc_probe_slot,
+};
+
 /* O2Micro extra registers */
 #define O2_SD_LOCK_WP          0xD3
 #define O2_SD_MULTI_VCC3V      0xEE
@@ -816,6 +837,22 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PCH_SDIO0,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_pch_sdio,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PCH_SDIO1,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_pch_sdio,
+       },
+
        {
                .vendor         = PCI_VENDOR_ID_O2,
                .device         = PCI_DEVICE_ID_O2_8120,
@@ -1206,6 +1243,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        host->hw_name = "PCI";
        host->ops = &sdhci_pci_ops;
        host->quirks = chip->quirks;
+       host->quirks2 = chip->quirks2;
 
        host->irq = pdev->irq;
 
@@ -1365,6 +1403,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
        chip->fixes = (const struct sdhci_pci_fixes *)ent->driver_data;
        if (chip->fixes) {
                chip->quirks = chip->fixes->quirks;
+               chip->quirks2 = chip->fixes->quirks2;
                chip->allow_runtime_pm = chip->fixes->allow_runtime_pm;
        }
        chip->num_slots = slots;
@@ -1379,6 +1418,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
 
        slots = chip->num_slots;        /* Quirk may have changed this */
 
+       pci_enable_msi(pdev);
+
        for (i = 0; i < slots; i++) {
                slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i);
                if (IS_ERR(slot)) {
@@ -1397,6 +1438,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
        return 0;
 
 free:
+       pci_disable_msi(pdev);
+
        pci_set_drvdata(pdev, NULL);
        kfree(chip);
 
@@ -1419,6 +1462,8 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
                for (i = 0; i < chip->num_slots; i++)
                        sdhci_pci_remove_slot(chip->slots[i]);
 
+               pci_disable_msi(pdev);
+
                pci_set_drvdata(pdev, NULL);
                kfree(chip);
        }
index b7f8b33c5f19f7202f66d65fd90ff14b503f8dd4..6dfa82e03c7e4964bff24a7e3fb9eb92468cd0d0 100644 (file)
@@ -300,20 +300,15 @@ static int sdhci_resume(struct device *dev)
 
        return sdhci_resume_host(host);
 }
-
-const struct dev_pm_ops sdhci_pm_ops = {
-       .suspend        = sdhci_suspend,
-       .resume         = sdhci_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume);
+
 static struct platform_driver sdhci_driver = {
        .driver = {
                .name   = "sdhci",
                .owner  = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     = &sdhci_pm_ops,
-#endif
        },
        .probe          = sdhci_probe,
        .remove         = __devexit_p(sdhci_remove),
index cb348569454b719a3b33c303de1ee7e17d6a148c..53b26502f6e2ec36123351833cc80a9fd35e8fd6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
 #include <linux/mmc/card.h>
 
 #include "sdhci-pltfm.h"
 
+#define NVQUIRK_FORCE_SDHCI_SPEC_200   BIT(0)
+#define NVQUIRK_ENABLE_BLOCK_GAP_DET   BIT(1)
+
+struct sdhci_tegra_soc_data {
+       struct sdhci_pltfm_data *pdata;
+       u32 nvquirks;
+};
+
+struct sdhci_tegra {
+       const struct tegra_sdhci_platform_data *plat;
+       const struct sdhci_tegra_soc_data *soc_data;
+};
+
 static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
 {
        u32 val;
@@ -46,7 +60,12 @@ static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
 
 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 {
-       if (unlikely(reg == SDHCI_HOST_VERSION)) {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_tegra *tegra_host = pltfm_host->priv;
+       const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
+
+       if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) &&
+                       (reg == SDHCI_HOST_VERSION))) {
                /* Erratum: Version register is invalid in HW. */
                return SDHCI_SPEC_200;
        }
@@ -56,6 +75,10 @@ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 
 static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_tegra *tegra_host = pltfm_host->priv;
+       const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
+
        /* Seems like we're getting spurious timeout and crc errors, so
         * disable signalling of them. In case of real errors software
         * timers should take care of eventually detecting them.
@@ -65,7 +88,8 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
 
        writel(val, host->ioaddr + reg);
 
-       if (unlikely(reg == SDHCI_INT_ENABLE)) {
+       if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) &&
+                       (reg == SDHCI_INT_ENABLE))) {
                /* Erratum: Must enable block gap interrupt detection */
                u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
                if (val & SDHCI_INT_CARD_INT)
@@ -76,10 +100,11 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
        }
 }
 
-static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci)
+static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
 {
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
-       struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_tegra *tegra_host = pltfm_host->priv;
+       const struct tegra_sdhci_platform_data *plat = tegra_host->plat;
 
        if (!gpio_is_valid(plat->wp_gpio))
                return -1;
@@ -98,7 +123,8 @@ static irqreturn_t carddetect_irq(int irq, void *data)
 static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
+       struct sdhci_tegra *tegra_host = pltfm_host->priv;
+       const struct tegra_sdhci_platform_data *plat = tegra_host->plat;
        u32 ctrl;
 
        ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
@@ -124,16 +150,44 @@ static struct sdhci_ops tegra_sdhci_ops = {
        .platform_8bit_width = tegra_sdhci_8bit,
 };
 
-static struct sdhci_pltfm_data sdhci_tegra_pdata = {
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+static struct sdhci_pltfm_data sdhci_tegra20_pdata = {
+       .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+                 SDHCI_QUIRK_SINGLE_POWER_WRITE |
+                 SDHCI_QUIRK_NO_HISPD_BIT |
+                 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
+       .ops  = &tegra_sdhci_ops,
+};
+
+static struct sdhci_tegra_soc_data soc_data_tegra20 = {
+       .pdata = &sdhci_tegra20_pdata,
+       .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
+                   NVQUIRK_ENABLE_BLOCK_GAP_DET,
+};
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+static struct sdhci_pltfm_data sdhci_tegra30_pdata = {
        .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+                 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
                  SDHCI_QUIRK_SINGLE_POWER_WRITE |
                  SDHCI_QUIRK_NO_HISPD_BIT |
                  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
        .ops  = &tegra_sdhci_ops,
 };
 
+static struct sdhci_tegra_soc_data soc_data_tegra30 = {
+       .pdata = &sdhci_tegra30_pdata,
+};
+#endif
+
 static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
-       { .compatible = "nvidia,tegra20-sdhci", },
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+       { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
+#endif
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
+#endif
        {}
 };
 MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
@@ -164,13 +218,22 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
 
 static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *match;
+       const struct sdhci_tegra_soc_data *soc_data;
+       struct sdhci_host *host;
        struct sdhci_pltfm_host *pltfm_host;
        struct tegra_sdhci_platform_data *plat;
-       struct sdhci_host *host;
+       struct sdhci_tegra *tegra_host;
        struct clk *clk;
        int rc;
 
-       host = sdhci_pltfm_init(pdev, &sdhci_tegra_pdata);
+       match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
+       if (match)
+               soc_data = match->data;
+       else
+               soc_data = &soc_data_tegra20;
+
+       host = sdhci_pltfm_init(pdev, soc_data->pdata);
        if (IS_ERR(host))
                return PTR_ERR(host);
 
@@ -187,7 +250,17 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                goto err_no_plat;
        }
 
-       pltfm_host->priv = plat;
+       tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL);
+       if (!tegra_host) {
+               dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n");
+               rc = -ENOMEM;
+               goto err_no_plat;
+       }
+
+       tegra_host->plat = plat;
+       tegra_host->soc_data = soc_data;
+
+       pltfm_host->priv = tegra_host;
 
        if (gpio_is_valid(plat->power_gpio)) {
                rc = gpio_request(plat->power_gpio, "sdhci_power");
@@ -283,7 +356,8 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct tegra_sdhci_platform_data *plat = pltfm_host->priv;
+       struct sdhci_tegra *tegra_host = pltfm_host->priv;
+       const struct tegra_sdhci_platform_data *plat = tegra_host->plat;
        int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 
        sdhci_remove_host(host, dead);
@@ -326,5 +400,5 @@ static struct platform_driver sdhci_tegra_driver = {
 module_platform_driver(sdhci_tegra_driver);
 
 MODULE_DESCRIPTION("SDHCI driver for Tegra");
-MODULE_AUTHOR(" Google, Inc.");
+MODULE_AUTHOR("Google, Inc.");
 MODULE_LICENSE("GPL v2");
index 8d66706824a6105ceeac2f63526372a4f0c521fd..8262cadfdab77b82e5590da88ff0042479d3a697 100644 (file)
@@ -2267,8 +2267,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 {
        irqreturn_t result;
        struct sdhci_host *host = dev_id;
-       u32 intmask;
-       int cardint = 0;
+       u32 intmask, unexpected = 0;
+       int cardint = 0, max_loops = 16;
 
        spin_lock(&host->lock);
 
@@ -2286,6 +2286,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                goto out;
        }
 
+again:
        DBG("*** %s got interrupt: 0x%08x\n",
                mmc_hostname(host->mmc), intmask);
 
@@ -2344,19 +2345,23 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
        intmask &= ~SDHCI_INT_CARD_INT;
 
        if (intmask) {
-               pr_err("%s: Unexpected interrupt 0x%08x.\n",
-                       mmc_hostname(host->mmc), intmask);
-               sdhci_dumpregs(host);
-
+               unexpected |= intmask;
                sdhci_writel(host, intmask, SDHCI_INT_STATUS);
        }
 
        result = IRQ_HANDLED;
 
-       mmiowb();
+       intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+       if (intmask && --max_loops)
+               goto again;
 out:
        spin_unlock(&host->lock);
 
+       if (unexpected) {
+               pr_err("%s: Unexpected interrupt 0x%08x.\n",
+                          mmc_hostname(host->mmc), unexpected);
+               sdhci_dumpregs(host);
+       }
        /*
         * We have to delay this as it calls back into the driver.
         */
@@ -2379,6 +2384,9 @@ int sdhci_suspend_host(struct sdhci_host *host)
        int ret;
        bool has_tuning_timer;
 
+       if (host->ops->platform_suspend)
+               host->ops->platform_suspend(host);
+
        sdhci_disable_card_detection(host);
 
        /* Disable tuning since we are suspending */
@@ -2423,12 +2431,24 @@ int sdhci_resume_host(struct sdhci_host *host)
        if (ret)
                return ret;
 
-       sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
-       mmiowb();
+       if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) &&
+           (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
+               /* Card keeps power but host controller does not */
+               sdhci_init(host, 0);
+               host->pwr = 0;
+               host->clock = 0;
+               sdhci_do_set_ios(host, &host->mmc->ios);
+       } else {
+               sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
+               mmiowb();
+       }
 
        ret = mmc_resume_host(host->mmc);
        sdhci_enable_card_detection(host);
 
+       if (host->ops->platform_resume)
+               host->ops->platform_resume(host);
+
        /* Set the re-tuning expiration flag */
        if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
            (host->tuning_mode == SDHCI_TUNING_MODE_1))
index ad265b96b75b4f25262186ff68a171202c4474ee..f761f23d2a28ccb287e1da22b2433478833b82f1 100644 (file)
@@ -275,6 +275,8 @@ struct sdhci_ops {
        void    (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
        int     (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
        void    (*hw_reset)(struct sdhci_host *host);
+       void    (*platform_suspend)(struct sdhci_host *host);
+       void    (*platform_resume)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
index 75a485448796e67d553cae26d3e3eda9fa329b98..aafaf0b6eb1c96bcf298307b180dca75a259b424 100644 (file)
@@ -286,7 +286,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
                         DMA_FROM_DEVICE);
        if (ret > 0) {
                host->dma_active = true;
-               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+               desc = dmaengine_prep_slave_sg(chan, sg, ret,
                        DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        }
 
@@ -335,7 +335,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
                         DMA_TO_DEVICE);
        if (ret > 0) {
                host->dma_active = true;
-               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+               desc = dmaengine_prep_slave_sg(chan, sg, ret,
                        DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        }
 
@@ -746,7 +746,6 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
        case MMC_SET_WRITE_PROT:
        case MMC_CLR_WRITE_PROT:
        case MMC_ERASE:
-       case MMC_GEN_CMD:
                tmp |= CMD_SET_RBSY;
                break;
        }
@@ -829,7 +828,6 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
        case MMC_SET_WRITE_PROT:
        case MMC_CLR_WRITE_PROT:
        case MMC_ERASE:
-       case MMC_GEN_CMD:
                mask = MASK_START_CMD | MASK_MRBSYE;
                break;
        default:
index 58da3c44acc5d129428198b7ec80f987fe73d68a..934b68e9efc34e50796495ea61a37d2ed598e155 100644 (file)
@@ -90,6 +90,15 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
        return 0;
 }
 
+static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev)
+{
+       mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100));
+}
+
+static const struct sh_mobile_sdhi_ops sdhi_ops = {
+       .cd_wakeup = sh_mobile_sdhi_cd_wakeup,
+};
+
 static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 {
        struct sh_mobile_sdhi *priv;
@@ -109,6 +118,12 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        mmc_data = &priv->mmc_data;
        p->pdata = mmc_data;
 
+       if (p->init) {
+               ret = p->init(pdev, &sdhi_ops);
+               if (ret)
+                       goto einit;
+       }
+
        snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
        priv->clk = clk_get(&pdev->dev, clk_name);
        if (IS_ERR(priv->clk)) {
@@ -117,8 +132,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                goto eclkget;
        }
 
-       clk_enable(priv->clk);
-
        mmc_data->hclk = clk_get_rate(priv->clk);
        mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
        mmc_data->get_cd = sh_mobile_sdhi_get_cd;
@@ -129,6 +142,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                        mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
                mmc_data->ocr_mask = p->tmio_ocr_mask;
                mmc_data->capabilities |= p->tmio_caps;
+               mmc_data->cd_gpio = p->cd_gpio;
 
                if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
                        priv->param_tx.slave_id = p->dma_slave_tx;
@@ -211,7 +225,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 
        dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
                 mmc_hostname(host->mmc), (unsigned long)
-                (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start),
+                (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start),
                 mmc_data->hclk / 1000000);
 
        return ret;
@@ -232,9 +246,11 @@ eirq_sdio:
 eirq_card_detect:
        tmio_mmc_host_remove(host);
 eprobe:
-       clk_disable(priv->clk);
        clk_put(priv->clk);
 eclkget:
+       if (p->cleanup)
+               p->cleanup(pdev);
+einit:
        kfree(priv);
        return ret;
 }
@@ -258,8 +274,11 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
                free_irq(irq, host);
        }
 
-       clk_disable(priv->clk);
        clk_put(priv->clk);
+
+       if (p->cleanup)
+               p->cleanup(pdev);
+
        kfree(priv);
 
        return 0;
index f96c536d130a287768c6317d1dfa9611d30297ac..d857f5c6e7d96d93fa771bee36178b93c901becf 100644 (file)
@@ -47,16 +47,14 @@ struct tmio_mmc_host {
        struct mmc_request      *mrq;
        struct mmc_data         *data;
        struct mmc_host         *mmc;
-       unsigned int            sdio_irq_enabled;
+
+       /* Controller power state */
+       bool                    power;
 
        /* Callbacks for clock / power control */
        void (*set_pwr)(struct platform_device *host, int state);
        void (*set_clk_div)(struct platform_device *host, int state);
 
-       int                     pm_error;
-       /* recognise system-wide suspend in runtime PM methods */
-       bool                    pm_global;
-
        /* pio related stuff */
        struct scatterlist      *sg_ptr;
        struct scatterlist      *sg_orig;
@@ -86,6 +84,7 @@ struct tmio_mmc_host {
        spinlock_t              lock;           /* protect host private data */
        unsigned long           last_req_ts;
        struct mutex            ios_lock;       /* protect set_ios() context */
+       bool                    native_hotplug;
 };
 
 int tmio_mmc_host_probe(struct tmio_mmc_host **host,
index 8253ec12003ed3c9001cdd7b8fed889179350d9b..fff9286048594fa7dad59922ea382af76901450b 100644 (file)
@@ -88,7 +88,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
 
        ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
        if (ret > 0)
-               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+               desc = dmaengine_prep_slave_sg(chan, sg, ret,
                        DMA_DEV_TO_MEM, DMA_CTRL_ACK);
 
        if (desc) {
@@ -169,7 +169,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
 
        ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
        if (ret > 0)
-               desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+               desc = dmaengine_prep_slave_sg(chan, sg, ret,
                        DMA_MEM_TO_DEV, DMA_CTRL_ACK);
 
        if (desc) {
index e21988901c367082f9fabb59eccb3b821b4b5843..9a7996ade58e8aaa597ca81758898669726a305d 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/mfd/tmio.h>
+#include <linux/mmc/cd-gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/tmio.h>
 #include <linux/module.h>
@@ -127,7 +128,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
        struct tmio_mmc_host *host = mmc_priv(mmc);
 
        if (enable) {
-               host->sdio_irq_enabled = 1;
                host->sdio_irq_mask = TMIO_SDIO_MASK_ALL &
                                        ~TMIO_SDIO_STAT_IOIRQ;
                sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
@@ -136,7 +136,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
                host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
                sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
                sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
-               host->sdio_irq_enabled = 0;
        }
 }
 
@@ -304,6 +303,7 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
 {
        struct mmc_data *data = host->data;
        int c = cmd->opcode;
+       u32 irq_mask = TMIO_MASK_CMD;
 
        /* Command 12 is handled by hardware */
        if (cmd->opcode == 12 && !cmd->arg) {
@@ -339,7 +339,9 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
                        c |= TRANSFER_READ;
        }
 
-       tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_CMD);
+       if (!host->native_hotplug)
+               irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
+       tmio_mmc_enable_mmc_irqs(host, irq_mask);
 
        /* Fire off the command */
        sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
@@ -758,7 +760,7 @@ fail:
 static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct tmio_mmc_host *host = mmc_priv(mmc);
-       struct tmio_mmc_data *pdata = host->pdata;
+       struct device *dev = &host->pdev->dev;
        unsigned long flags;
 
        mutex_lock(&host->ios_lock);
@@ -766,13 +768,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        spin_lock_irqsave(&host->lock, flags);
        if (host->mrq) {
                if (IS_ERR(host->mrq)) {
-                       dev_dbg(&host->pdev->dev,
+                       dev_dbg(dev,
                                "%s.%d: concurrent .set_ios(), clk %u, mode %u\n",
                                current->comm, task_pid_nr(current),
                                ios->clock, ios->power_mode);
                        host->mrq = ERR_PTR(-EINTR);
                } else {
-                       dev_dbg(&host->pdev->dev,
+                       dev_dbg(dev,
                                "%s.%d: CMD%u active since %lu, now %lu!\n",
                                current->comm, task_pid_nr(current),
                                host->mrq->cmd->opcode, host->last_req_ts, jiffies);
@@ -788,13 +790,15 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        spin_unlock_irqrestore(&host->lock, flags);
 
        /*
-        * pdata->power == false only if COLD_CD is available, otherwise only
-        * in short time intervals during probing or resuming
+        * host->power toggles between false and true in both cases - either
+        * or not the controller can be runtime-suspended during inactivity.
+        * But if the controller has to be kept on, the runtime-pm usage_count
+        * is kept positive, so no suspending actually takes place.
         */
        if (ios->power_mode == MMC_POWER_ON && ios->clock) {
-               if (!pdata->power) {
-                       pm_runtime_get_sync(&host->pdev->dev);
-                       pdata->power = true;
+               if (!host->power) {
+                       pm_runtime_get_sync(dev);
+                       host->power = true;
                }
                tmio_mmc_set_clock(host, ios->clock);
                /* power up SD bus */
@@ -805,9 +809,9 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        } else if (ios->power_mode != MMC_POWER_UP) {
                if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
                        host->set_pwr(host->pdev, 0);
-               if (pdata->power) {
-                       pdata->power = false;
-                       pm_runtime_put(&host->pdev->dev);
+               if (host->power) {
+                       host->power = false;
+                       pm_runtime_put(dev);
                }
                tmio_mmc_clk_stop(host);
        }
@@ -913,7 +917,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
        else
                mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
-       pdata->power = false;
+       _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
+                                 mmc->caps & MMC_CAP_NEEDS_POLL ||
+                                 mmc->caps & MMC_CAP_NONREMOVABLE);
+
+       _host->power = false;
        pm_runtime_enable(&pdev->dev);
        ret = pm_runtime_resume(&pdev->dev);
        if (ret < 0)
@@ -926,14 +934,13 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
         *  3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL
         *  4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE
         *
-        *  While we increment the rtpm counter for all scenarios when the mmc
-        *  core activates us by calling an appropriate set_ios(), we must
+        *  While we increment the runtime PM counter for all scenarios when
+        *  the mmc core activates us by calling an appropriate set_ios(), we
+        *  must additionally ensure that in case 2) the tmio mmc hardware stays
         *  additionally ensure that in case 2) the tmio mmc hardware stays
         *  powered on during runtime for the card detection to work.
         */
-       if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD
-               || mmc->caps & MMC_CAP_NEEDS_POLL
-               || mmc->caps & MMC_CAP_NONREMOVABLE))
+       if (_host->native_hotplug)
                pm_runtime_get_noresume(&pdev->dev);
 
        tmio_mmc_clk_stop(_host);
@@ -963,9 +970,19 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
                irq_mask |= TMIO_MASK_READOP;
        if (!_host->chan_tx)
                irq_mask |= TMIO_MASK_WRITEOP;
+       if (!_host->native_hotplug)
+               irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
 
        tmio_mmc_enable_mmc_irqs(_host, irq_mask);
 
+       if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
+               ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
+               if (ret < 0) {
+                       tmio_mmc_host_remove(_host);
+                       return ret;
+               }
+       }
+
        *host = _host;
 
        return 0;
@@ -983,22 +1000,22 @@ EXPORT_SYMBOL(tmio_mmc_host_probe);
 void tmio_mmc_host_remove(struct tmio_mmc_host *host)
 {
        struct platform_device *pdev = host->pdev;
+       struct tmio_mmc_data *pdata = host->pdata;
+       struct mmc_host *mmc = host->mmc;
 
-       /*
-        * We don't have to manipulate pdata->power here: if there is a card in
-        * the slot, the runtime PM is active and our .runtime_resume() will not
-        * be run. If there is no card in the slot and the platform can suspend
-        * the controller, the runtime PM is suspended and pdata->power == false,
-        * so, our .runtime_resume() will not try to detect a card in the slot.
-        */
-       if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD
-               || host->mmc->caps & MMC_CAP_NEEDS_POLL
-               || host->mmc->caps & MMC_CAP_NONREMOVABLE)
+       if (pdata->flags & TMIO_MMC_USE_GPIO_CD)
+               /*
+                * This means we can miss a card-eject, but this is anyway
+                * possible, because of delayed processing of hotplug events.
+                */
+               mmc_cd_gpio_free(mmc);
+
+       if (!host->native_hotplug)
                pm_runtime_get_sync(&pdev->dev);
 
        dev_pm_qos_hide_latency_limit(&pdev->dev);
 
-       mmc_remove_host(host->mmc);
+       mmc_remove_host(mmc);
        cancel_work_sync(&host->done);
        cancel_delayed_work_sync(&host->delayed_reset_work);
        tmio_mmc_release_dma(host);
@@ -1007,7 +1024,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
        pm_runtime_disable(&pdev->dev);
 
        iounmap(host->ctl);
-       mmc_free_host(host->mmc);
+       mmc_free_host(mmc);
 }
 EXPORT_SYMBOL(tmio_mmc_host_remove);
 
@@ -1021,8 +1038,6 @@ int tmio_mmc_host_suspend(struct device *dev)
        if (!ret)
                tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);
 
-       host->pm_error = pm_runtime_put_sync(dev);
-
        return ret;
 }
 EXPORT_SYMBOL(tmio_mmc_host_suspend);
@@ -1032,20 +1047,10 @@ int tmio_mmc_host_resume(struct device *dev)
        struct mmc_host *mmc = dev_get_drvdata(dev);
        struct tmio_mmc_host *host = mmc_priv(mmc);
 
-       /* The MMC core will perform the complete set up */
-       host->pdata->power = false;
-
-       host->pm_global = true;
-       if (!host->pm_error)
-               pm_runtime_get_sync(dev);
-
-       if (host->pm_global) {
-               /* Runtime PM resume callback didn't run */
-               tmio_mmc_reset(host);
-               tmio_mmc_enable_dma(host, true);
-               host->pm_global = false;
-       }
+       tmio_mmc_reset(host);
+       tmio_mmc_enable_dma(host, true);
 
+       /* The MMC core will perform the complete set up */
        return mmc_resume_host(mmc);
 }
 EXPORT_SYMBOL(tmio_mmc_host_resume);
@@ -1062,19 +1067,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
 {
        struct mmc_host *mmc = dev_get_drvdata(dev);
        struct tmio_mmc_host *host = mmc_priv(mmc);
-       struct tmio_mmc_data *pdata = host->pdata;
 
        tmio_mmc_reset(host);
        tmio_mmc_enable_dma(host, true);
 
-       if (pdata->power) {
-               /* Only entered after a card-insert interrupt */
-               if (!mmc->card)
-                       tmio_mmc_set_ios(mmc, &mmc->ios);
-               mmc_detect_change(mmc, msecs_to_jiffies(100));
-       }
-       host->pm_global = false;
-
        return 0;
 }
 EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
index ecff765579dd395bbb73bacecd8b54bf375c7ee6..5d53c5760a6cfa71adc20fe92d862497acb33aff 100644 (file)
@@ -93,7 +93,6 @@
 #include <linux/fs.h>
 #include <linux/ioctl.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/pci.h>
 
 #include <linux/mtd/mtd.h>
index e585263161b949ee1b863725ae627f6a4595fc7f..288594163c22da60e4c932ea16e78c3b9bf1f6bf 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <linux/mtd/mtd.h>
 
index e8e9fec23553d06ea34410633c12c8cce558fdb2..0259cf5830222e4c2da75f921be90c8517bd8c15 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
index 50387fd4009bdbe464af98703e0653debf4baaf6..64c9cbaf86a1905abdb8b8663740af687b883db3 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach-types.h>
-#include <asm/system.h>
 
 #include <mach/reg_nand.h>
 #include <mach/reg_umi.h>
index 7db6555ed3ba630f2935ce65b25200295b1754db..590dd5cceed66164ff93686f9f355818883ac0b3 100644 (file)
@@ -835,7 +835,7 @@ int gpmi_send_command(struct gpmi_nand_data *this)
                | BM_GPMI_CTRL0_ADDRESS_INCREMENT
                | BF_GPMI_CTRL0_XFER_COUNT(this->command_length);
        pio[1] = pio[2] = 0;
-       desc = channel->device->device_prep_slave_sg(channel,
+       desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
@@ -848,8 +848,7 @@ int gpmi_send_command(struct gpmi_nand_data *this)
 
        sg_init_one(sgl, this->cmd_buffer, this->command_length);
        dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
-       desc = channel->device->device_prep_slave_sg(channel,
-                                       sgl, 1, DMA_MEM_TO_DEV, 1);
+       desc = dmaengine_prep_slave_sg(channel, sgl, 1, DMA_MEM_TO_DEV, 1);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -880,8 +879,7 @@ int gpmi_send_data(struct gpmi_nand_data *this)
                | BF_GPMI_CTRL0_ADDRESS(address)
                | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
        pio[1] = 0;
-       desc = channel->device->device_prep_slave_sg(channel,
-                                       (struct scatterlist *)pio,
+       desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 1 error\n");
@@ -890,7 +888,7 @@ int gpmi_send_data(struct gpmi_nand_data *this)
 
        /* [2] send DMA request */
        prepare_data_dma(this, DMA_TO_DEVICE);
-       desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
+       desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                                1, DMA_MEM_TO_DEV, 1);
        if (!desc) {
                pr_err("step 2 error\n");
@@ -916,7 +914,7 @@ int gpmi_read_data(struct gpmi_nand_data *this)
                | BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
                | BF_GPMI_CTRL0_XFER_COUNT(this->upper_len);
        pio[1] = 0;
-       desc = channel->device->device_prep_slave_sg(channel,
+       desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
@@ -926,8 +924,8 @@ int gpmi_read_data(struct gpmi_nand_data *this)
 
        /* [2] : send DMA request */
        prepare_data_dma(this, DMA_FROM_DEVICE);
-       desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
-                                               1, DMA_DEV_TO_MEM, 1);
+       desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
+                                       1, DMA_DEV_TO_MEM, 1);
        if (!desc) {
                pr_err("step 2 error\n");
                return -1;
@@ -972,8 +970,7 @@ int gpmi_send_page(struct gpmi_nand_data *this,
        pio[4] = payload;
        pio[5] = auxiliary;
 
-       desc = channel->device->device_prep_slave_sg(channel,
-                                       (struct scatterlist *)pio,
+       desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
        if (!desc) {
                pr_err("step 2 error\n");
@@ -1007,7 +1004,7 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                | BF_GPMI_CTRL0_ADDRESS(address)
                | BF_GPMI_CTRL0_XFER_COUNT(0);
        pio[1] = 0;
-       desc = channel->device->device_prep_slave_sg(channel,
+       desc = dmaengine_prep_slave_sg(channel,
                                (struct scatterlist *)pio, 2,
                                DMA_TRANS_NONE, 0);
        if (!desc) {
@@ -1036,7 +1033,7 @@ int gpmi_read_page(struct gpmi_nand_data *this,
        pio[3] = geo->page_size;
        pio[4] = payload;
        pio[5] = auxiliary;
-       desc = channel->device->device_prep_slave_sg(channel,
+       desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 1);
        if (!desc) {
@@ -1055,7 +1052,7 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                | BF_GPMI_CTRL0_ADDRESS(address)
                | BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
        pio[1] = 0;
-       desc = channel->device->device_prep_slave_sg(channel,
+       desc = dmaengine_prep_slave_sg(channel,
                                (struct scatterlist *)pio, 2,
                                DMA_TRANS_NONE, 1);
        if (!desc) {
index 9abd4eb86dc1bf7a38b692657696062f8dc7e974..dd5e04813b7623cf2125dcdf41e3da8848c6b9c5 100644 (file)
@@ -70,7 +70,6 @@ static const char *version =
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 6057b30417a2f5d89e17ab5f80e1aba7c4d73822..0910dce3996d08a64c5c158056e0430c472962f1 100644 (file)
@@ -229,7 +229,6 @@ static int dma;
 #include <linux/bitops.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 
index 980e65c14936e28957ac29187853b555a0d60a09..5bed4c4e25084fad1d3e2607cc95a03446e1a380 100644 (file)
@@ -47,7 +47,6 @@
 #include <pcmcia/ds.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
 
index b920d829692aa35394962f87910678bfe1d4cbb7..0c76186bb9e75aff0c3f7024780a8802d025285b 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/inet.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <linux/uaccess.h>
 #include <linux/errno.h>
index 98a5a7d867f5049d12afd2c9ccc944d1f18c8faf..034c16b60e962c0a33125b924072643be5621f24 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
index 7cb2785e209dd0f52a70bfe9581aa267283b3cf8..ec03b401620a6f3fc649940d1379b2b6e29deed8 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/io.h>         /* CRIS_LED_* I/O functions */
 #include <asm/irq.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/ethernet.h>
 #include <asm/cache.h>
 #include <arch/io_interface_mux.h>
index e61b2f82ba3a8d001e4f0824b22e70e1ef0b2391..66df936380859b55ab0b8b15595319bfeb98c98a 100644 (file)
@@ -95,7 +95,6 @@ earlier 3Com products.
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /*====================================================================*/
 
index b23253b9f74235f75bab3ea5355d7aed7d3fbcfe..a556c01e011b1cf8521b83186c66dd0741c4ee4d 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
index fbab1367505f028be3ec1845b2b94e07bf139f8b..49d76bd0dc86fb12bc7a519fdc5a14d5a6eded82 100644 (file)
@@ -54,7 +54,6 @@ static const char version[] =
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "8390.h"
index 5337dd0a59b08086b8d89bd0f7081d6504afa96e..ccf07942ff6eb51a1fcf8c0620285d78c91e9743 100644 (file)
@@ -34,7 +34,6 @@ static const char version[] =
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 3ad5d2f9a49cc42622038ff1986ac8505952f66a..923959275a82228e07e323d8da9abd84e586b1c7 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/amigaints.h>
index c30adcc9828a401955a575dc67583f90aa470096..11476ca95e93978b4e60e9108d3805a8e4797ab0 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <net/ax88796.h>
 
-#include <asm/system.h>
 
 /* Rename the lib8390.c functions to show that they are in this driver */
 #define __ei_open ax_ei_open
index c5bd8eb7a9f598d14665c31cfba6f9ff49f83f46..e1b3941bd14948e74b9c3b9b0684c01e06104f88 100644 (file)
@@ -46,7 +46,6 @@
 #include <pcmcia/cisreg.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
index d16dc53c181317b4d2567039012693f336a0483f..ed55ce85ebbf10187855b1d2591c68df1da872f0 100644 (file)
@@ -48,7 +48,6 @@ static const char version[] =
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 6428f9e7a554d7b994da4a9f982b44cc01359421..ba1b5c95531f30a71a04a8c37e9bc5de498ec060 100644 (file)
@@ -59,7 +59,6 @@ static const char version[] =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 48c4948750d1df3c01133c1221b24a11711e2444..dbefd5658c146265c1c8a646e432be59ab0e4926 100644 (file)
@@ -45,9 +45,9 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/ecard.h>
 #include <asm/io.h>
+#include <asm/system_info.h>
 
 #define EI_SHIFT(x)    (ei_local->reg_offset[x])
 
index d42938b6b596e32b6a00b6c562fa129cc3600d60..52f70f999c00a6b490f281eb3a6d0f7c5890b02b 100644 (file)
@@ -33,7 +33,6 @@ static const char version[] =
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "8390.h"
index 113f1e075a2644bdab095bf087d02799f3c82238..37fa89aa4578564ae58f3394a82a7b434894371d 100644 (file)
@@ -33,7 +33,6 @@ static const char version[] =
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "8390.h"
index e77f624e819476214ea146b7cc46b511420df4f7..b329f5c0d62b25203db832aa151dda371bcf4a1c 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/irq.h>
index 69490ae018ea5e8a9cfbb25d06287a6280492319..479409bf2e3c9b81394f0a611b929392023c8971 100644 (file)
@@ -46,7 +46,6 @@ static const char *version =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index af5d9822cad969125c824c160a829f6b137768b9..88ccc8b14f0a4b09aa8097a5f8a5dbcbacb128ba 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/bitops.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/hwtest.h>
 #include <asm/macints.h>
index 9b9c77d5a65cca2858d4a35c6210500363c54dfd..7fc28f2d28a68119e52b405587185ea64383937a 100644 (file)
@@ -29,7 +29,6 @@ static const char version1[] =
 #include <linux/etherdevice.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index f92ea2a65a576d20f5732975794421cfc142ad28..d04911d33b647080278f81678869c032e1a3c853 100644 (file)
@@ -53,7 +53,6 @@ static const char version2[] =
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "8390.h"
index 922b32036c6380d296334a9503e8e334f9f4cc0f..ef85839f43d850a0df5b7a38ce6cb1c3a8875bbd 100644 (file)
@@ -76,7 +76,6 @@ static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.o
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 3fab04a0034a3aa68ecc45544cf3cdf9e682af31..5e8845febfb8f40be7cdacaa2b398434a37e8dfe 100644 (file)
@@ -54,7 +54,6 @@ static int options[MAX_UNITS];
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index 2a3e8057feaef80341460ecd1854c55d3dfdd61d..a2f8b2b8e27cd429dcce71d8f30b1b5ba61c6818 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/mm.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index f2a4e5de18c4197f0ef3fd17cdf0a0186887864d..de1af0bfed4c1687f7ddf0ea24fbc37a2bb62087 100644 (file)
@@ -49,7 +49,6 @@
 #include <pcmcia/cisreg.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
index 77efec44fea0caa8cf11a8380b71b609c8f302d8..7a68590f28047dd17a6ffca82619836eb6aa2925 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 1cc306a83ff7d2f6760b4d7073893d343c311926..b0fbce39661a7154e5d2c6af00ea543acce2d107 100644 (file)
@@ -69,7 +69,6 @@ static const char version[] =
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index bb87053eb3da9aa2764966ed4c3d2df0bb646512..923e42aedcfd40580683a8ee32137dd054003f77 100644 (file)
@@ -57,7 +57,6 @@ static const char *version = "smc-ultra32.c: 06/97 v1.00\n";
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 3b903759980a01c318ead3411249adec47382e57..8df4c41572306d9f4fad96567964778b7455c23a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <mach-se/mach/se.h>
 #include <asm/machvec.h>
index c175fadb597bf12949d9cfaa8b976d0ad40fc57d..03eb3eed49fa42d2485f606710c3347525040c43 100644 (file)
@@ -39,7 +39,6 @@ static const char version[] =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index bcd27323b2030dccb635def78f29dcebc0df4192..7818e6397e913870dcbfab18b5d171af127f99f4 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/zorro.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
index 6c3b1c0adaa0e589563f080ca62e8eb4f69f0907..7219123fa0a433985bd24a6d775d70aea6365529 100644 (file)
@@ -78,7 +78,6 @@
 #include <net/sock.h>
 #include <net/ip.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
index 1b046f58d58fa7c20384a6192da4e30fc4ad6208..6e722dc37db7aa69ec639f47540ae5a9d0e1572d 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/socket.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
index cc7b9e46780c2c7cfbcbd94b8607fa154b49d2ed..e10ffad525a788e06bae64c8581f47280be9c4fc 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/system.h>
 
 #define TX_BUFFERS 15
 #define RX_BUFFERS 25
index 9f62504d008691244ba81d495b47ff64d16a882a..64d0d9c1afa271c9ae73cb1818cdb6b7318d36f4 100644 (file)
@@ -88,7 +88,6 @@ Revision History:
 #include <linux/crc32.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index 7dc508e5c72e89e0b7d964c98d4e1aef09e60cb2..75299f500ee5b700f4c9d276dcbe0b2db6550475 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic.h>
index 4e2d68a4de8aae7fb9404067d18508cbf8be4d19..8baff4e5d964ed6f172f0cd1f44a3ac2c3a5ce0e 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
index 56bc47a94186aa746f445a426017dd2ed6f05255..9af3c307862c1aead9d545aa51588385849325c0 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/mvme147hw.h>
index ebdb9e238a8d822e1863aa26adfb99563ed47ece..9f59bf63514b1151b0961975990f12ae14713e5e 100644 (file)
@@ -154,7 +154,6 @@ Include Files
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* ----------------------------------------------------------------------------
 Defines
index e3fe3504e198f400916b7b1f506da18c26330900..d7a3533d990b165774a585343a440217b90ec517 100644 (file)
@@ -95,7 +95,6 @@ static char lancestr[] = "LANCE";
 #include <linux/of_device.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
index 7b71387cf93cfe6ed34e1baf0cdc9ff21a81e1d1..4e4bb38758680728cd2178610fef2724f5b6f662 100644 (file)
@@ -48,7 +48,6 @@
 #include <net/checksum.h>
 #include <net/ip.h>
 
-#include <asm/system.h>
 #include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
index 30fee428c4891efe65eee52337f7e54061e5eb5d..b9406cbfc1808a85678734c56a011eb3c41fe309 100644 (file)
 #include <linux/delay.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <linux/atomic.h>
index 932fdccc339aea30e95d39e668adbdc565dd2f3d..e285f384b0966dfe2ab1e3b138f99b5e1a2bb610 100644 (file)
@@ -99,7 +99,6 @@ static char *version =
 #include <linux/bitops.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
 #include <asm/macints.h>
index 682750c052c846839be5b648b53778e7b7941150..414f0eea104967884024ace326cdebaa45c97f15 100644 (file)
@@ -46,7 +46,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $,  Bjorn Ekwall (bj
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <asm/system.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index afc5aaac6b600fd904738c0dfcc66ba13de4ced4..2e2bc60ee8116246ea9fd2effe9cd5be8360966e 100644 (file)
@@ -122,7 +122,6 @@ static const char version[] =
 #include <linux/skbuff.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* Constant definitions for the DE-620 registers, commands and bits */
 #include "de620.h"
index 586b46fd4eed18782faffab05914f084701b07ec..3d94797c8f9ba6efd583d5fe7060c64db981e0b8 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/crc32.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index c3f0178fb5cb07dbc3e10b959e45492968821d05..a992d1f7e0d2befc49a2681169689131543758a2 100644 (file)
@@ -163,7 +163,6 @@ static char *version =
 #include <linux/jiffies.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 
 
index 0230319ddb59eef8780e1be5ee7032ec0ee9a993..2418faf2251aacc2e91877859ee185c95c251516 100644 (file)
@@ -57,7 +57,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /*====================================================================*/
 
index ed6925f11479fc51f9eba55451ac4b7ce742d5f8..e8984b05990527665cb283eb270fa70f63fa6bdb 100644 (file)
@@ -63,7 +63,6 @@ static const char version[] =
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /* use 0 for production, 1 for verification, 2..7 for debug */
index ef43f3e951c5d6c2394168bd10b9fc133213c554..278e791afe0097ab834a4ebe5edeefd157778203 100644 (file)
@@ -106,7 +106,6 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp@paradise.net.
 #include <linux/semaphore.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 7a4ad4a079171b6b60aab46c4c999d926fd73a7b..7f49fd54c521b0599e7511780fbd9bd91d177537 100644 (file)
@@ -148,7 +148,6 @@ static const char version[] =
 #include <linux/bitops.h>
 #include <linux/ethtool.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 3fc649e54a3245ad13b654e2d1932e33f712accb..cc2e66ad4436e1852a6b1f12977c0126db80ae1c 100644 (file)
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 406a12b464042026b74e687709b5c5ffb3388614..067db3f13e918ddc7ac896ab0212e20921fd8d31 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/ecard.h>
index a43649735a04d93f706818d1cfde7c1b77539d1a..bd1f1ef91e1910f81f454a7332337870fa031331 100644 (file)
 #include <linux/if_arp.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index e877371680a9b1417f53b7b4c73f770b4e6c3d43..9010cea68bc3094a4b9b18b06cae1aa7d9796cd7 100644 (file)
@@ -1616,11 +1616,8 @@ static struct vio_driver ibmveth_driver = {
        .probe          = ibmveth_probe,
        .remove         = ibmveth_remove,
        .get_desired_dma = ibmveth_get_desired_dma,
-       .driver         = {
-               .name   = ibmveth_driver_name,
-               .owner  = THIS_MODULE,
-               .pm = &ibmveth_pm_ops,
-       }
+       .name           = ibmveth_driver_name,
+       .pm             = &ibmveth_pm_ops,
 };
 
 static int __init ibmveth_module_init(void)
index f30db1c4660068ff50bedc468160afe4a6aa1b54..bc58f1dc22f50f204e7ec46045052999b0437d92 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/crc32.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
index 75af1afe46c87a8778bd0eea51bc44139f8a115e..5e1ca0f0509098dd6e571b289df35f8886d7b21d 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/types.h>
 #include <linux/inet_lro.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 
 static char mv643xx_eth_driver_name[] = "mv643xx_eth";
 static char mv643xx_eth_driver_version[] = "1.4";
index 45a6333588e67a43d0b465ed650258e2a5e19935..efec6b60b3276e891b9e2930e237e810e4311b27 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <linux/pxa168_eth.h>
 
index 0686b93f1857a911db624c9bf5c1818475b3b031..f84dd2dc82b6181605bd74250eddf07593644095 100644 (file)
@@ -458,7 +458,7 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
        if (sg_dma_len(&ctl->sg) % 4)
                sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
 
-       ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
+       ctl->adesc = dmaengine_prep_slave_sg(ctl->chan,
                &ctl->sg, 1, DMA_MEM_TO_DEV,
                DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
        if (!ctl->adesc)
@@ -570,7 +570,7 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev)
 
                sg_dma_len(sg) = DMA_BUFFER_SIZE;
 
-               ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
+               ctl->adesc = dmaengine_prep_slave_sg(ctl->chan,
                        sg, 1, DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
 
index 5b89fd377ae3723c0bfed198c8a145dda867b53f..95dd39ffb2309d340097946be548e55cf5dadfae 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/dma.h>
index e640e23460defa42257a31b5676972397e8a4bdd..b9680ba5a32523df25e453b8d847a785fe35def1 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/slab.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
index c24b46cbfe27af958ffc6a4b1603cfbb4ea74928..d52728b3c436e1d9d2d97ff0746fd7a845be6c4b 100644 (file)
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #define DRV_NAME "ns83820"
 
index 22a8de00bf022817d362afffd4eeea9fbf01c9b6..6338ef8606ae3af9133ce53a1188f22230e2a73e 100644 (file)
@@ -81,7 +81,6 @@
 #include <linux/prefetch.h>
 #include <net/tcp.h>
 
-#include <asm/system.h>
 #include <asm/div64.h>
 #include <asm/irq.h>
 
index 8561dd25db66a40b67aebfaf83b9bff742d76a35..aca13046e4326a1fd2f6be0864dac06749e2647b 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #define TX_WORK_PER_LOOP  64
 #define RX_WORK_PER_LOOP  64
index 46c1932048cbb459cc0f02547c78307caf73eacc..e02f04d7f3adb24112149238885a0b302a0d3faf 100644 (file)
@@ -140,7 +140,6 @@ static int xcvr[NUM_UNITS];                         /* The data transfer mode. */
 #include <linux/delay.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 27c358c8f4dcc496fd01e841c35b74a9307cbb05..7b23554f80b6c0f8540bccddea0c9ae31c75f35e 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/pci-aspm.h>
 #include <linux/prefetch.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 7b819bd8c416e2bd618624dc30ccb53c68722acf..df808ac8cb6535c88ad0eca0c3aacdd98976e83d 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/ecard.h>
 #include <asm/io.h>
 
index 79899077444620aebe0a04a152f073893b0bde87..698edbbfc1496d8d58aa9d869771f14563d8c241 100644 (file)
@@ -47,7 +47,6 @@ static const char version[] =
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index d12e48a7861d4f966bcf9713c2d82d518a96c2bf..04393b5fef718c5a71877e8da9c6e351cf73823b 100644 (file)
@@ -53,7 +53,6 @@
 #include <pcmcia/ss.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /*====================================================================*/
index 3c22955607328df9b80826257f362a8804d572d0..ce4df61b4b5684e1ab3a6d92c3773803a1613beb 100644 (file)
@@ -99,7 +99,6 @@
 #include <net/checksum.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index f359863b5340e203255c32c8cda04f7e13bc3711..2a83fc57edba58efd1ae7163ddd91bc70aff72d3 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #include "sunbmac.h"
 
index ba041596e04629e5513732910d99d8b48175d3f4..558409ff40582fa9f5cd1ae91248f9d214c51d3e 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index 8b627e2f798d42e3ce6c4953ace642d1ee2f6c7e..b95e7e681b38cfc59e5566fb6c53cce2174c9bd9 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/bitops.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
index 139d6b410d687cc9655b13aafcfbce4c63d454db..7d4a040d84a2df2e729ee64bc7db22e6f5f1c5bb 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
index 92a037a8228a3f0c004347442517fe9c2d0c4588..38e3ae9155b7080fc6d0baf5c7b84eadb9f4723d 100644 (file)
@@ -1259,10 +1259,7 @@ static struct vio_driver vnet_port_driver = {
        .id_table       = vnet_port_match,
        .probe          = vnet_port_probe,
        .remove         = vnet_port_remove,
-       .driver         = {
-               .name   = "vnet_port",
-               .owner  = THIS_MODULE,
-       }
+       .name           = "vnet_port",
 };
 
 static int __init vnet_init(void)
index 840e0e9031f579588fe30f6966976508b383225e..277c93e9ff4d7201470fd0fdea50a691c28f24de 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/platform_device.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tsi108.h>
 
index 5c69c6f93fb80ec79b1ed7801b970f49b7c282b7..94a1f94f74b89f7a4d9a05c47ea0a44672c1adc8 100644 (file)
@@ -89,7 +89,6 @@
 #include <pcmcia/ciscode.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #ifndef MANFID_COMPAQ
index 2a5a34d2d67b9cc9838a851dc9656d25d311fb7c..64783a0d545ac0d3fd6ba56c03ab74d73b5cbaef 100644 (file)
@@ -13,7 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
index f1aea0c98333aed66ea757b7368f72a79a82fbfb..acb636963e90724c05792425ed7290493c1a97aa 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /* --------------------------------------------------------------------- */
index 18d8affecd1bff7b0aacdc22adacb8daab59b2c4..76d54774ba82ac0fba45dc774b556e64dd5124e4 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index bc02968cee161f017dc3749cc6d57d8928b059d0..aed1a6105b24d01dc339cdfe9e9f68ad19b1ada2 100644 (file)
@@ -17,7 +17,6 @@
  * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
  */
 #include <linux/module.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
 #include <linux/crc16.h>
index 33655814448e3a5485cce6d923961c615c986781..efc6c97163a727a99ef389c2bff4a85991e3a747 100644 (file)
 #include <net/ax25.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 696327773fbe468e91edbf527d01ec0be54cd450..5a6412ecce739b7c21b395705742d42e1da6e4c7 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/bitops.h>
 #include <linux/random.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/firmware.h>
index 2a51363d9fed2947e8c60831a6c106b077266302..168c8f41d09f534986977a3d673663b74e433cdf 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
index 617a446d126c0d158bfdba1ac5b2c21a9401ad35..4351296dde323f0267b924a956bcb7009e07241b 100644 (file)
 #include <linux/pci.h>
 #include <linux/rtnetlink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <net/irda/wrapper.h>
index b71998d0b5b495132b4e07e80f7fae6a93f634ef..32eb94ece6c1b258497f9b12334c680729f48dc7 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/in.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
index 1a5a316cc96881de81104dfe3b5dd4cc99375bb6..bed62d9c53c868ec607fa37ffc4b8697a1ca61a0 100644 (file)
@@ -113,7 +113,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
 
 #include <net/neighbour.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
 
index 0a0a6643cf3a806576e2d870374506a2a19701a9..1252d9c726a77c4692e12ca095eff80d2a4097ad 100644 (file)
@@ -75,7 +75,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <linux/timer.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <net/checksum.h>
 #include <asm/unaligned.h>
index 69345dfae0fdcef3773b94d21f394b0814c20ae0..d4c9db3da22a0c8b6c0561e9d3afb5f10b879c98 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/sched.h>
index d7c292aa76b1528f9b979afe3a6c17d48e080a02..b15ac81d46fafeea5d8db7c25180991a707acd3c 100644 (file)
@@ -68,7 +68,6 @@
 #include <net/checksum.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "3c359.h"
 
index 515f122777abcb361891196de2fb5a95d9343a8e..b715e6b444daa8265bc94708c1c856db0ceb2d3f 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 91b684630fc54695096b270a000b8270abbbf79a..356e28e4881b9f3c7ffd3da1aaace0d4343488f5 100644 (file)
@@ -63,7 +63,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #define PCMCIA
 #include "ibmtr.c"
index 8d71e0d290626e3ea7cb4c55522da6c2d1222505..3e4b4f091113e0ffe6712689276e06c1fd0fac44 100644 (file)
 #include <net/checksum.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "lanstreamer.h"
 
index 1cdc034f6aecd7bfef9ebb828956994886a534ce..28adcdf3b14cb1b46e963debc4d9ed5e9dc27232 100644 (file)
@@ -28,7 +28,6 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index fd8dce90c957502eb2e98e2ee4d3f67e8fff2554..0e234741cc791af3ca5d6d372862c297e51f5cfe 100644 (file)
 #include <net/net_namespace.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "olympic.h"
 
index 8d362e64a40e45ddfbac4bd68a16befe7152dd33..62d90e40f9ecee49778793c0739c908b130cca67 100644 (file)
@@ -31,7 +31,6 @@ static const char version[] = "proteon.c: v1.00 02/01/2003 by Jochen Friedrich\n
 #include <linux/trdevice.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
index 46db5c5395b2c6c4d1a7935054690647e1b4e401..ee11e93dc30ea5bd3bdf50e4eb70c3683d1c11c2 100644 (file)
@@ -38,7 +38,6 @@ static const char version[] = "skisa.c: v1.03 09/12/2002 by Jochen Friedrich\n";
 #include <linux/trdevice.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
index 029846a98636323bac69ceacdc04b67092b2085a..cb35fb79e01649fdc556eea7aef94ad18f51de14 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/bitops.h>
 #include <linux/firmware.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
index 102f896bbc58e849ef7cea66f6e4941675298e96..be4813e0366c2fa1488bc9ceeb6cc62c43bd98ee 100644 (file)
@@ -98,7 +98,6 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
 #include <linux/firmware.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
index d3e788a9cd1c9ea90c29fd41f31d37e1dd5f9ebe..fb9918da5792916f63ed8f26aa84e8f3f6e60c2c 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 74d7f76d14a3e505667a2fb65dabcbd07935ce36..bb8c72c79c6f31c9c932b2960df6a2c2f009a08e 100644 (file)
@@ -69,7 +69,6 @@
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /* Uncomment to enable debugging */
index 48ab38a34c5a956057ae8342d7fbf2a145376017..147614ed86aa8ae5d4a8a5451304337a70bb0960 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
index fe8d060d8fffb153b78791fa11f802b7c2d911cc..c676de7de024801c3b9841fb4a7e8f00a4402426 100644 (file)
@@ -93,7 +93,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index 33b67d88fceb312ce013af94af0583e4f9e2f420..cf4903355a34eb78b6bbdd488b9c35849f0afe97 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include "hd64570.h"
 
index efc0db101183f2eb26673190c4eaaebe5e17ec9c..e2779faa6c4f9c651cc115dae455dd72423f19c9 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include "hd64572.h"
 
index 7beeb9b88a3b5f7d1400755c2813716a7d784c7e..a73b49eb87e37a150c6096299a08460ad921d32d 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c8531612eea950b873593ba88740f809448fd7b7..de3bbf43fc5ac14f41ee9d76eeacb1f059eeaab3 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/sdla.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
index e862369b4a6dd694b150a6ff19abef3764da29c9..d7a65e141d1a0bff90f9d3f1d691fb7876226ba7 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
index ddc061dd150ce47438020f28424a7449e9ab66a5..520a4b2eb9cc8b2d6c2a1e1281cf243b8ec8a9f4 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/scatterlist.h>
 #include <linux/crypto.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include <linux/netdevice.h>
index c983c10e0f6a8336b855dc810f237172cf1c6ef2..630577dd3a7add9166ef8668797cd38076f58b9e 100644 (file)
@@ -37,7 +37,6 @@
 #include <pcmcia/ds.h>
 
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include "airo.h"
 
index 3010cee7b95ab935264c91e37627c2061928b24c..6c87a823f5a9d4c6ec228651687b14c7fb545c8e 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/timer.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
index ec295c4f677d583876a92351638b0e15c31578a7..ded03d226a7108cab5f8bf698747000fa364e5c4 100644 (file)
@@ -48,7 +48,6 @@
 #include <pcmcia/ciscode.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/wireless.h>
 
 #include "atmel.h"
index 851fa10241e1e94d8ffa8a6635e7b80e14d2fead..c5404cb59e083d81ad04ca66a07cc18686b3c15b 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/if_arp.h>
 
 #include "prismcompat.h"
index 04fec1fa6e0b6915b5c3e8e4938a668246df7586..86a738bf591c601db5572d16f2b104b07a1f132a 100644 (file)
@@ -53,7 +53,6 @@
 #include <net/iw_handler.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
index 98fbf54f6004144e832f713034728a8b302c45ee..00f6e69c1dcd6f47e3f1e916cf26f923b9f0e1ea 100644 (file)
@@ -53,7 +53,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include "wl3501.h"
 
index b764ac22d523276a59c4055b914cba90f7e13d64..44d01afafe9c2633e1008b8c4d9be9a2a979cf48 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/hwtest.h>
 #include <linux/proc_fs.h>
index 7e62d15d60f693cd3404adb7c657ff20d8316430..bba81216b4dbbbaee8b097a10a2ce505bd4bea9d 100644 (file)
@@ -78,8 +78,9 @@ err0:
 EXPORT_SYMBOL(of_get_named_gpio_flags);
 
 /**
- * of_gpio_count - Count GPIOs for a device
+ * of_gpio_named_count - Count GPIOs for a device
  * @np:                device node to count GPIOs for
+ * @propname:  property name containing gpio specifier(s)
  *
  * The function returns the count of GPIOs specified for a node.
  *
@@ -93,14 +94,14 @@ EXPORT_SYMBOL(of_get_named_gpio_flags);
  * defines four GPIOs (so this function will return 4), two of which
  * are not specified.
  */
-unsigned int of_gpio_count(struct device_node *np)
+unsigned int of_gpio_named_count(struct device_node *np, const char* propname)
 {
        unsigned int cnt = 0;
 
        do {
                int ret;
 
-               ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells",
+               ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
                                                 cnt, NULL);
                /* A hole in the gpios = <> counts anyway. */
                if (ret < 0 && ret != -EEXIST)
@@ -109,7 +110,7 @@ unsigned int of_gpio_count(struct device_node *np)
 
        return cnt;
 }
-EXPORT_SYMBOL(of_gpio_count);
+EXPORT_SYMBOL(of_gpio_named_count);
 
 /**
  * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
@@ -228,7 +229,7 @@ void of_gpiochip_remove(struct gpio_chip *chip)
 }
 
 /* Private function for resolving node pointer to gpio_chip */
-static int of_gpiochip_is_match(struct gpio_chip *chip, void *data)
+static int of_gpiochip_is_match(struct gpio_chip *chip, const void *data)
 {
        return chip->of_node == data;
 }
index 0610e91bceb27ec5d7d71b7ddfedf5f6dbdb0d84..432d4bbcc62a21d3ae3e91e3cf98a31fd09acf41 100644 (file)
@@ -55,7 +55,6 @@
 
 #include <asm/pdc.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 
index 95930d016235ae3a39fdfe71e1b409291d21d370..1f9e9fefb8e7d97f21516b0541beaf0206f366a8 100644 (file)
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/io.h>            /* read/write functions */
 #ifdef CONFIG_SUPERIO
 #include <asm/superio.h>
index e8857647e21090c460d4a99a39102ea142698c88..052fa230bc776b7d91b3377abcf947bf260e83f3 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 #include <asm/ropes.h>
 #include <asm/hardware.h>      /* for register_parisc_driver() stuff */
index 1dd68f502634e4725fa9a2c97328d370236bcbdf..9694c1e783a558bbdf4ea6b11a1674abe78c55ef 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
 
 #include <pcmcia/ss.h>
 
 #include <mach/hardware.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
-#include <asm/gpio.h>
 
 #include <mach/board.h>
 #include <mach/at91rm9200_mc.h>
@@ -70,7 +70,7 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf)
 {
        struct at91_cf_socket *cf = _cf;
 
-       if (irq == cf->board->det_pin) {
+       if (irq == gpio_to_irq(cf->board->det_pin)) {
                unsigned present = at91_cf_present(cf);
 
                /* kick pccard as needed */
@@ -96,8 +96,8 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
 
        /* NOTE: CF is always 3VCARD */
        if (at91_cf_present(cf)) {
-               int rdy = cf->board->irq_pin;   /* RDY/nIRQ */
-               int vcc = cf->board->vcc_pin;
+               int rdy = gpio_is_valid(cf->board->irq_pin);    /* RDY/nIRQ */
+               int vcc = gpio_is_valid(cf->board->vcc_pin);
 
                *sp = SS_DETECT | SS_3VCARD;
                if (!rdy || gpio_get_value(rdy))
@@ -118,7 +118,7 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
        cf = container_of(sock, struct at91_cf_socket, socket);
 
        /* switch Vcc if needed and possible */
-       if (cf->board->vcc_pin) {
+       if (gpio_is_valid(cf->board->vcc_pin)) {
                switch (s->Vcc) {
                        case 0:
                                gpio_set_value(cf->board->vcc_pin, 0);
@@ -222,7 +222,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
        struct resource         *io;
        int                     status;
 
-       if (!board || !board->det_pin || !board->rst_pin)
+       if (!board || !gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
                return -ENODEV;
 
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -242,7 +242,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
        status = gpio_request(board->det_pin, "cf_det");
        if (status < 0)
                goto fail0;
-       status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
+       status = request_irq(gpio_to_irq(board->det_pin), at91_cf_irq, 0, driver_name, cf);
        if (status < 0)
                goto fail00;
        device_init_wakeup(&pdev->dev, 1);
@@ -251,7 +251,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
        if (status < 0)
                goto fail0a;
 
-       if (board->vcc_pin) {
+       if (gpio_is_valid(board->vcc_pin)) {
                status = gpio_request(board->vcc_pin, "cf_vcc");
                if (status < 0)
                        goto fail0b;
@@ -263,15 +263,15 @@ static int __init at91_cf_probe(struct platform_device *pdev)
         * unless we report that we handle everything (sigh).
         * (Note:  DK board doesn't wire the IRQ pin...)
         */
-       if (board->irq_pin) {
+       if (gpio_is_valid(board->irq_pin)) {
                status = gpio_request(board->irq_pin, "cf_irq");
                if (status < 0)
                        goto fail0c;
-               status = request_irq(board->irq_pin, at91_cf_irq,
+               status = request_irq(gpio_to_irq(board->irq_pin), at91_cf_irq,
                                IRQF_SHARED, driver_name, cf);
                if (status < 0)
                        goto fail0d;
-               cf->socket.pci_irq = board->irq_pin;
+               cf->socket.pci_irq = gpio_to_irq(board->irq_pin);
        } else
                cf->socket.pci_irq = nr_irqs + 1;
 
@@ -290,7 +290,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
        }
 
        pr_info("%s: irqs det #%d, io #%d\n", driver_name,
-               board->det_pin, board->irq_pin);
+               gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin));
 
        cf->socket.owner = THIS_MODULE;
        cf->socket.dev.parent = &pdev->dev;
@@ -312,19 +312,19 @@ fail2:
 fail1:
        if (cf->socket.io_offset)
                iounmap((void __iomem *) cf->socket.io_offset);
-       if (board->irq_pin) {
-               free_irq(board->irq_pin, cf);
+       if (gpio_is_valid(board->irq_pin)) {
+               free_irq(gpio_to_irq(board->irq_pin), cf);
 fail0d:
                gpio_free(board->irq_pin);
        }
 fail0c:
-       if (board->vcc_pin)
+       if (gpio_is_valid(board->vcc_pin))
                gpio_free(board->vcc_pin);
 fail0b:
        gpio_free(board->rst_pin);
 fail0a:
        device_init_wakeup(&pdev->dev, 0);
-       free_irq(board->det_pin, cf);
+       free_irq(gpio_to_irq(board->det_pin), cf);
 fail00:
        gpio_free(board->det_pin);
 fail0:
@@ -341,15 +341,15 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
        pcmcia_unregister_socket(&cf->socket);
        release_mem_region(io->start, resource_size(io));
        iounmap((void __iomem *) cf->socket.io_offset);
-       if (board->irq_pin) {
-               free_irq(board->irq_pin, cf);
+       if (gpio_is_valid(board->irq_pin)) {
+               free_irq(gpio_to_irq(board->irq_pin), cf);
                gpio_free(board->irq_pin);
        }
-       if (board->vcc_pin)
+       if (gpio_is_valid(board->vcc_pin))
                gpio_free(board->vcc_pin);
        gpio_free(board->rst_pin);
        device_init_wakeup(&pdev->dev, 0);
-       free_irq(board->det_pin, cf);
+       free_irq(gpio_to_irq(board->det_pin), cf);
        gpio_free(board->det_pin);
        kfree(cf);
        return 0;
@@ -363,9 +363,9 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
        struct at91_cf_data     *board = cf->board;
 
        if (device_may_wakeup(&pdev->dev)) {
-               enable_irq_wake(board->det_pin);
-               if (board->irq_pin)
-                       enable_irq_wake(board->irq_pin);
+               enable_irq_wake(gpio_to_irq(board->det_pin));
+               if (gpio_is_valid(board->irq_pin))
+                       enable_irq_wake(gpio_to_irq(board->irq_pin));
        }
        return 0;
 }
@@ -376,9 +376,9 @@ static int at91_cf_resume(struct platform_device *pdev)
        struct at91_cf_data     *board = cf->board;
 
        if (device_may_wakeup(&pdev->dev)) {
-               disable_irq_wake(board->det_pin);
-               if (board->irq_pin)
-                       disable_irq_wake(board->irq_pin);
+               disable_irq_wake(gpio_to_irq(board->det_pin));
+               if (gpio_is_valid(board->irq_pin))
+                       disable_irq_wake(gpio_to_irq(board->irq_pin));
        }
 
        return 0;
index 693577e0fefc3c52a037bd9af6e63567f67a43c8..c2e997a570bffd84bf09392091f8fb44603888ba 100644 (file)
@@ -475,7 +475,7 @@ static void __devexit bcm63xx_cb_exit(struct pci_dev *dev)
        bcm63xx_cb_dev = NULL;
 }
 
-static struct pci_device_id bcm63xx_cb_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(bcm63xx_cb_table) = {
        {
                .vendor         = PCI_VENDOR_ID_BROADCOM,
                .device         = BCM6348_CPU_ID,
index 49221395101e6ae8590fc09ac28af2552df1cbd4..ac1a2232eab954e0df850bacbd27eee77e2df584 100644 (file)
@@ -310,18 +310,7 @@ static struct platform_driver bfin_cf_driver = {
        .remove = __devexit_p(bfin_cf_remove),
 };
 
-static int __init bfin_cf_init(void)
-{
-       return platform_driver_register(&bfin_cf_driver);
-}
-
-static void __exit bfin_cf_exit(void)
-{
-       platform_driver_unregister(&bfin_cf_driver);
-}
-
-module_init(bfin_cf_init);
-module_exit(bfin_cf_exit);
+module_platform_driver(bfin_cf_driver);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver");
index d9ea192c4001ed9e315d21bac96b2ab37361376f..673c14ea11e3570f8bcf7ed872d46412b496d9ac 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/device.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
index 5b7c22784aff9713054b5b3f34d3ff9bed9ad91d..a484b1fb338288c2756376f31ed8bffd2aaa0997 100644 (file)
@@ -172,12 +172,12 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
        if ((sock->board_type == BOARD_TYPE_DB1200) ||
            (sock->board_type == BOARD_TYPE_DB1300)) {
                ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,
-                                 IRQF_DISABLED, "pcmcia_insert", sock);
+                                 0, "pcmcia_insert", sock);
                if (ret)
                        goto out1;
 
                ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq,
-                                 IRQF_DISABLED, "pcmcia_eject", sock);
+                                 0, "pcmcia_eject", sock);
                if (ret) {
                        free_irq(sock->insert_irq, sock);
                        goto out1;
@@ -580,18 +580,7 @@ static struct platform_driver db1x_pcmcia_socket_driver = {
        .remove         = __devexit_p(db1x_pcmcia_socket_remove),
 };
 
-int __init db1x_pcmcia_socket_load(void)
-{
-       return platform_driver_register(&db1x_pcmcia_socket_driver);
-}
-
-void  __exit db1x_pcmcia_socket_unload(void)
-{
-       platform_driver_unregister(&db1x_pcmcia_socket_driver);
-}
-
-module_init(db1x_pcmcia_socket_load);
-module_exit(db1x_pcmcia_socket_unload);
+module_platform_driver(db1x_pcmcia_socket_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards");
index 06ad3e5e7d3d246b9acab61dd049a3f41c430f50..7647d232e9e21929db320efc1d1feb1e12b2268e 100644 (file)
@@ -365,17 +365,7 @@ static struct platform_driver electra_cf_driver = {
        .remove   = electra_cf_remove,
 };
 
-static int __init electra_cf_init(void)
-{
-       return platform_driver_register(&electra_cf_driver);
-}
-module_init(electra_cf_init);
-
-static void __exit electra_cf_exit(void)
-{
-       platform_driver_unregister(&electra_cf_driver);
-}
-module_exit(electra_cf_exit);
+module_platform_driver(electra_cf_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
index 3e447d0387b7d358b2d3f88effdfad3757ac886c..4e8831bdb6efb2af19e4a25114cbc80daabc3bb7 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <pcmcia/ss.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "i82092aa.h"
 MODULE_LICENSE("GPL");
 
 /* PCI core routines */
-static struct pci_device_id i82092aa_pci_ids[] = {
-       {
-             .vendor = PCI_VENDOR_ID_INTEL,
-             .device = PCI_DEVICE_ID_INTEL_82092AA_0,
-             .subvendor = PCI_ANY_ID,
-             .subdevice = PCI_ANY_ID,
-        },
-        {} 
+static DEFINE_PCI_DEVICE_TABLE(i82092aa_pci_ids) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) },
+       { }
 };
 MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
 
index 72a033a2acdb262684cf02a164efb6ee89cea408..e6f3d17dd2b4d296d39ad2a0a22d3c2c01bec362 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/ss.h>
 
index 2adb0106a0397a3800b9c707493f871490d5636f..a26f38c6402afc82343d019bc2d5cd48efc4f7a9 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/ss.h>
 
index 1511ff71c87b013914491e2695a97995253a694f..296514155cd59cafa1292ca28bad72534d9916e4 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/addrspace.h>
 
 #include <pcmcia/ss.h>
index 271a590a5f3cb5418ee8a53c8b59ae7edcef32c2..a3a851e49321542ac84659f4f3315219163430ae 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
@@ -1304,15 +1303,4 @@ static struct platform_driver m8xx_pcmcia_driver = {
        .remove = m8xx_remove,
 };
 
-static int __init m8xx_init(void)
-{
-       return platform_driver_register(&m8xx_pcmcia_driver);
-}
-
-static void __exit m8xx_exit(void)
-{
-       platform_driver_unregister(&m8xx_pcmcia_driver);
-}
-
-module_init(m8xx_init);
-module_exit(m8xx_exit);
+module_platform_driver(m8xx_pcmcia_driver);
index 96c72e90b79c4c1ff26bcc0e754dbb1c34350017..253e3867dec713e8d1b5df9167a8da2337cb7465 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <pcmcia/ss.h>
 
-#include <asm/system.h>
 
 #include "pd6729.h"
 #include "i82365.h"
@@ -763,13 +762,8 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
        kfree(socket);
 }
 
-static struct pci_device_id pd6729_pci_ids[] = {
-       {
-               .vendor         = PCI_VENDOR_ID_CIRRUS,
-               .device         = PCI_DEVICE_ID_CIRRUS_6729,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-       },
+static DEFINE_PCI_DEVICE_TABLE(pd6729_pci_ids) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) },
        { }
 };
 MODULE_DEVICE_TABLE(pci, pd6729_pci_ids);
index 66a54222bbf4d83a9ce45c0cf6dfac359cd1c230..490bb82b5bdbd0be8394590f0c7c65b85088f238 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/smemc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <mach/pxa2xx-regs.h>
 #include <asm/mach-types.h>
 
index adfae4987a42a7077242ccceedcc9af1df6b2d2d..cb0c37ec7f246e1c978955a22736fbf5c6978669 100644 (file)
@@ -177,18 +177,7 @@ static struct platform_driver viper_pcmcia_driver = {
        .id_table       = viper_pcmcia_id_table,
 };
 
-static int __init viper_pcmcia_init(void)
-{
-       return platform_driver_register(&viper_pcmcia_driver);
-}
-
-static void __exit viper_pcmcia_exit(void)
-{
-       return platform_driver_unregister(&viper_pcmcia_driver);
-}
-
-module_init(viper_pcmcia_init);
-module_exit(viper_pcmcia_exit);
+module_platform_driver(viper_pcmcia_driver);
 
 MODULE_DEVICE_TABLE(platform, viper_pcmcia_id_table);
 MODULE_LICENSE("GPL");
index a3ee89a6dd0e04c27b7881bf020ff30f03e6868d..6eecd7cddf5796b681b224e45a52a77476884d39 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "soc_common.h"
 #include "sa11xx_base.h"
index e0433f571962743d1191fd47f53253f2a65f04de..a2bc6ee1702e14f2c722b510c304863c7b9d0060 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/timer.h>
 
 #include <mach/hardware.h>
-#include <asm/system.h>
 
 #include "soc_common.h"
 
index 71aeed93037c57485b330ee703efdc9b5bae4198..d6881514d38e701c8913e8d57cbd47ab2a5a1d27 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/pm.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
index 310160bffe382c46ac6cda7a3c848bbcb2646d0a..cbe15fc37411943e0a0686966973f0476d16cfc0 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/ss.h>
 #include "tcic.h"
index c6d36b3a6ce89b04fb84540be5a32203fb5405b2..cd0a315d922b5ae0f7b32c6e82a5b6155a0ddefd 100644 (file)
@@ -563,11 +563,8 @@ static int __devinit vrc4173_cardu_setup(char *options)
 
 __setup("vrc4173_cardu=", vrc4173_cardu_setup);
 
-static struct pci_device_id vrc4173_cardu_id_table[] __devinitdata = {
-       {       .vendor         = PCI_VENDOR_ID_NEC,
-               .device         = PCI_DEVICE_ID_NEC_NAPCCARD,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID, },
+static DEFINE_PCI_DEVICE_TABLE(vrc4173_cardu_id_table) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NAPCCARD) },
         {0, }
 };
 
index 379f4218857d9446a82882e353d5300621254d99..fd5fbd10aad07e853878ff53a3c5280dbc330bdc 100644 (file)
@@ -21,7 +21,6 @@
 #include <pcmcia/cistpl.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
 #define MEM_MAP_SIZE   0x400000
@@ -321,18 +320,7 @@ static struct platform_driver xxs1500_pcmcia_socket_driver = {
        .remove         = __devexit_p(xxs1500_pcmcia_remove),
 };
 
-int __init xxs1500_pcmcia_socket_load(void)
-{
-       return platform_driver_register(&xxs1500_pcmcia_socket_driver);
-}
-
-void  __exit xxs1500_pcmcia_socket_unload(void)
-{
-       platform_driver_unregister(&xxs1500_pcmcia_socket_driver);
-}
-
-module_init(xxs1500_pcmcia_socket_load);
-module_exit(xxs1500_pcmcia_socket_unload);
+module_platform_driver(xxs1500_pcmcia_socket_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems");
index 849c0c11d2af84797ca686d6cf3f85cf3ba5de89..d07f9ac8c41ddb550688a4b2b3c3fc4dcbf295be 100644 (file)
@@ -1352,7 +1352,7 @@ static const struct dev_pm_ops yenta_pm_ops = {
                .driver_data    = CARDBUS_TYPE_##type,  \
        }
 
-static struct pci_device_id yenta_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(yenta_table) = {
        CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI),
 
        /*
index 2dc02c972ce959aad865c321d639c1557eae41ab..2a262f5c5c0ca5753671f74903a2e49d8e65d382 100644 (file)
@@ -26,6 +26,10 @@ config ACER_WMI
        depends on RFKILL || RFKILL = n
        depends on ACPI_WMI
        select INPUT_SPARSEKMAP
+       # Acer WMI depends on ACPI_VIDEO when ACPI is enabled
+       # but for select to work, need to select ACPI_VIDEO's dependencies, ick
+        select VIDEO_OUTPUT_CONTROL if ACPI
+        select ACPI_VIDEO if ACPI
        ---help---
          This is a driver for newer Acer (and Wistron) laptops. It adds
          wireless radio and bluetooth control, and on some laptops,
@@ -54,7 +58,6 @@ config ACERHDF
 config ASUS_LAPTOP
        tristate "Asus Laptop Extras"
        depends on ACPI
-       depends on !ACPI_ASUS
        select LEDS_CLASS
        select NEW_LEDS
        select BACKLIGHT_CLASS_DEVICE
@@ -460,10 +463,9 @@ config INTEL_MENLOW
          If unsure, say N.
 
 config EEEPC_LAPTOP
-       tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
+       tristate "Eee PC Hotkey Driver"
        depends on ACPI
        depends on INPUT
-       depends on EXPERIMENTAL
        depends on RFKILL || RFKILL = n
        depends on HOTPLUG_PCI
        select BACKLIGHT_CLASS_DEVICE
@@ -482,11 +484,10 @@ config EEEPC_LAPTOP
          doesn't work on your Eee PC, try eeepc-wmi instead.
 
 config ASUS_WMI
-       tristate "ASUS WMI Driver (EXPERIMENTAL)"
+       tristate "ASUS WMI Driver"
        depends on ACPI_WMI
        depends on INPUT
        depends on HWMON
-       depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
        depends on HOTPLUG_PCI
@@ -501,7 +502,7 @@ config ASUS_WMI
          be called asus-wmi.
 
 config ASUS_NB_WMI
-       tristate "Asus Notebook WMI Driver (EXPERIMENTAL)"
+       tristate "Asus Notebook WMI Driver"
        depends on ASUS_WMI
        ---help---
          This is a driver for newer Asus notebooks. It adds extra features
@@ -514,7 +515,7 @@ config ASUS_NB_WMI
          here.
 
 config EEEPC_WMI
-       tristate "Eee PC WMI Driver (EXPERIMENTAL)"
+       tristate "Eee PC WMI Driver"
        depends on ASUS_WMI
        ---help---
          This is a driver for newer Eee PC laptops. It adds extra features
@@ -559,38 +560,6 @@ config MSI_WMI
         To compile this driver as a module, choose M here: the module will
         be called msi-wmi.
 
-config ACPI_ASUS
-       tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
-       depends on ACPI
-       select BACKLIGHT_CLASS_DEVICE
-       ---help---
-         This driver provides support for extra features of ACPI-compatible
-         ASUS laptops. As some of Medion laptops are made by ASUS, it may also
-         support some Medion laptops (such as 9675 for example).  It makes all
-         the extra buttons generate standard ACPI events that go through
-         /proc/acpi/events, and (on some models) adds support for changing the
-         display brightness and output, switching the LCD backlight on and off,
-         and most importantly, allows you to blink those fancy LEDs intended
-         for reporting mail and wireless status.
-
-         Note: display switching code is currently considered EXPERIMENTAL,
-         toying with these values may even lock your machine.
-
-         All settings are changed via /proc/acpi/asus directory entries. Owner
-         and group for these entries can be set with asus_uid and asus_gid
-         parameters.
-
-         More information and a userspace daemon for handling the extra buttons
-         at <http://acpi4asus.sf.net>.
-
-         If you have an ACPI-compatible ASUS laptop, say Y or M here. This
-         driver is still under development, so if your laptop is unsupported or
-         something works not quite as expected, please use the mailing list
-         available on the above page (acpi4asus-user@lists.sourceforge.net).
-
-         NOTE: This driver is deprecated and will probably be removed soon,
-         use asus-laptop instead.
-
 config TOPSTAR_LAPTOP
        tristate "Topstar Laptop Extras"
        depends on ACPI
@@ -604,6 +573,7 @@ config TOPSTAR_LAPTOP
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
        depends on ACPI
+       depends on ACPI_WMI
        select LEDS_CLASS
        select NEW_LEDS
        depends on BACKLIGHT_CLASS_DEVICE
@@ -746,13 +716,18 @@ config XO15_EBOOK
 
 config SAMSUNG_LAPTOP
        tristate "Samsung Laptop driver"
-       depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86
+       depends on X86
+       depends on RFKILL || RFKILL = n
+       depends on BACKLIGHT_CLASS_DEVICE
+       select LEDS_CLASS
+       select NEW_LEDS
        ---help---
          This module implements a driver for a wide range of different
          Samsung laptops.  It offers control over the different
-         function keys, wireless LED, LCD backlight level, and
-         sometimes provides a "performance_control" sysfs file to allow
-         the performance level of the laptop to be changed.
+         function keys, wireless LED, LCD backlight level.
+
+         It may also provide some sysfs files described in
+         <file:Documentation/ABI/testing/sysfs-platform-samsung-laptop>
 
          To compile this driver as a module, choose M here: the module
          will be called samsung-laptop.
@@ -781,4 +756,14 @@ config SAMSUNG_Q10
          This driver provides support for backlight control on Samsung Q10
          and related laptops, including Dell Latitude X200.
 
+config APPLE_GMUX
+       tristate "Apple Gmux Driver"
+       depends on PNP
+       select BACKLIGHT_CLASS_DEVICE
+       ---help---
+         This driver provides support for the gmux device found on many
+         Apple laptops, which controls the display mux for the hybrid
+         graphics as well as the backlight. Currently only backlight
+         control is supported by the driver.
+
 endif # X86_PLATFORM_DEVICES
index bb947657d490e2cd8ad9520447042778835f5de7..bf7e4f935b1755ca9562af71c697ac1303d1d8f8 100644 (file)
@@ -29,9 +29,12 @@ obj-$(CONFIG_PANASONIC_LAPTOP)       += panasonic-laptop.o
 obj-$(CONFIG_INTEL_MENLOW)     += intel_menlow.o
 obj-$(CONFIG_ACPI_WMI)         += wmi.o
 obj-$(CONFIG_MSI_WMI)          += msi-wmi.o
-obj-$(CONFIG_ACPI_ASUS)                += asus_acpi.o
 obj-$(CONFIG_TOPSTAR_LAPTOP)   += topstar-laptop.o
+
+# toshiba_acpi must link after wmi to ensure that wmi devices are found
+# before toshiba_acpi initializes
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
+
 obj-$(CONFIG_TOSHIBA_BT_RFKILL)        += toshiba_bluetooth.o
 obj-$(CONFIG_INTEL_SCU_IPC)    += intel_scu_ipc.o
 obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
@@ -46,3 +49,4 @@ obj-$(CONFIG_MXM_WMI)         += mxm-wmi.o
 obj-$(CONFIG_INTEL_MID_POWER_BUTTON)   += intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)   += intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)      += samsung-q10.o
+obj-$(CONFIG_APPLE_GMUX)       += apple-gmux.o
index 1e5290b5396dc2e290864782500b5caf28c0a747..c1a3fd8e12438bb0d4a995f107981edfe7c68a89 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/input/sparse-keymap.h>
 
 #include <acpi/acpi_drivers.h>
+#include <acpi/video.h>
 
 MODULE_AUTHOR("Carlos Corbacho");
 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
@@ -105,13 +106,19 @@ static const struct key_entry acer_wmi_keymap[] = {
        {KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
        {KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
        {KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
+       {KE_KEY, 0x29, {KEY_PROG3} },    /* P_Key for TM8372 */
        {KE_IGNORE, 0x41, {KEY_MUTE} },
        {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
+       {KE_IGNORE, 0x4d, {KEY_PREVIOUSSONG} },
        {KE_IGNORE, 0x43, {KEY_NEXTSONG} },
+       {KE_IGNORE, 0x4e, {KEY_NEXTSONG} },
        {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
+       {KE_IGNORE, 0x4f, {KEY_PLAYPAUSE} },
        {KE_IGNORE, 0x45, {KEY_STOP} },
+       {KE_IGNORE, 0x50, {KEY_STOP} },
        {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
        {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
+       {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
        {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
        {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
        {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
@@ -153,7 +160,14 @@ struct lm_return_value {
        u16 reserved;
 } __attribute__((packed));
 
-struct wmid3_gds_input_param { /* Get Device Status input parameter */
+struct wmid3_gds_set_input_param {     /* Set Device Status input parameter */
+       u8 function_num;        /* Function Number */
+       u8 hotkey_number;       /* Hotkey Number */
+       u16 devices;            /* Set Device */
+       u8 volume_value;        /* Volume Value */
+} __attribute__((packed));
+
+struct wmid3_gds_get_input_param {     /* Get Device Status input parameter */
        u8 function_num;        /* Function Number */
        u8 hotkey_number;       /* Hotkey Number */
        u16 devices;            /* Get Device */
@@ -171,6 +185,11 @@ struct hotkey_function_type_aa {
        u8 length;
        u16 handle;
        u16 commun_func_bitmap;
+       u16 application_func_bitmap;
+       u16 media_func_bitmap;
+       u16 display_func_bitmap;
+       u16 others_func_bitmap;
+       u8 commun_fn_key_number;
 } __attribute__((packed));
 
 /*
@@ -207,6 +226,7 @@ static int force_series;
 static bool ec_raw_mode;
 static bool has_type_aa;
 static u16 commun_func_bitmap;
+static u8 commun_fn_key_number;
 
 module_param(mailled, int, 0444);
 module_param(brightness, int, 0444);
@@ -466,6 +486,15 @@ static struct dmi_system_id acer_quirks[] = {
                },
                .driver_data = &quirk_lenovo_ideapad_s205,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Lenovo Ideapad S205 (Brazos)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Brazos"),
+               },
+               .driver_data = &quirk_lenovo_ideapad_s205,
+       },
        {
                .callback = dmi_matched,
                .ident = "Lenovo 3000 N200",
@@ -478,6 +507,25 @@ static struct dmi_system_id acer_quirks[] = {
        {}
 };
 
+static int video_set_backlight_video_vendor(const struct dmi_system_id *d)
+{
+       interface->capability &= ~ACER_CAP_BRIGHTNESS;
+       pr_info("Brightness must be controlled by generic video driver\n");
+       return 0;
+}
+
+static const struct dmi_system_id video_vendor_dmi_table[] = {
+       {
+               .callback = video_set_backlight_video_vendor,
+               .ident = "Acer TravelMate 4750",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
+               },
+       },
+       {}
+};
+
 /* Find which quirks are needed for a particular vendor/ model pair */
 static void find_quirks(void)
 {
@@ -536,8 +584,7 @@ struct acpi_buffer *result)
        return status;
 }
 
-static acpi_status AMW0_get_u32(u32 *value, u32 cap,
-struct wmi_interface *iface)
+static acpi_status AMW0_get_u32(u32 *value, u32 cap)
 {
        int err;
        u8 result;
@@ -607,7 +654,7 @@ struct wmi_interface *iface)
        return AE_OK;
 }
 
-static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
+static acpi_status AMW0_set_u32(u32 value, u32 cap)
 {
        struct wmab_args args;
 
@@ -692,6 +739,7 @@ static const struct acpi_device_id norfkill_ids[] = {
        { "VPC2004", 0},
        { "IBM0068", 0},
        { "LEN0068", 0},
+       { "SNY5001", 0},        /* sony-laptop in charge */
        { "", 0},
 };
 
@@ -827,8 +875,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
        return status;
 }
 
-static acpi_status WMID_get_u32(u32 *value, u32 cap,
-struct wmi_interface *iface)
+static acpi_status WMID_get_u32(u32 *value, u32 cap)
 {
        acpi_status status;
        u8 tmp;
@@ -864,7 +911,7 @@ struct wmi_interface *iface)
        return status;
 }
 
-static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
+static acpi_status WMID_set_u32(u32 value, u32 cap)
 {
        u32 method_id = 0;
        char param;
@@ -912,13 +959,13 @@ static acpi_status wmid3_get_device_status(u32 *value, u16 device)
        struct wmid3_gds_return_value return_value;
        acpi_status status;
        union acpi_object *obj;
-       struct wmid3_gds_input_param params = {
+       struct wmid3_gds_get_input_param params = {
                .function_num = 0x1,
-               .hotkey_number = 0x01,
+               .hotkey_number = commun_fn_key_number,
                .devices = device,
        };
        struct acpi_buffer input = {
-               sizeof(struct wmid3_gds_input_param),
+               sizeof(struct wmid3_gds_get_input_param),
                &params
        };
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -981,19 +1028,28 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
        acpi_status status;
        union acpi_object *obj;
        u16 devices;
-       struct wmid3_gds_input_param params = {
+       struct wmid3_gds_get_input_param get_params = {
                .function_num = 0x1,
-               .hotkey_number = 0x01,
+               .hotkey_number = commun_fn_key_number,
                .devices = commun_func_bitmap,
        };
-       struct acpi_buffer input = {
-               sizeof(struct wmid3_gds_input_param),
-               &params
+       struct acpi_buffer get_input = {
+               sizeof(struct wmid3_gds_get_input_param),
+               &get_params
+       };
+       struct wmid3_gds_set_input_param set_params = {
+               .function_num = 0x2,
+               .hotkey_number = commun_fn_key_number,
+               .devices = commun_func_bitmap,
+       };
+       struct acpi_buffer set_input = {
+               sizeof(struct wmid3_gds_set_input_param),
+               &set_params
        };
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
        struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
 
-       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &get_input, &output);
        if (ACPI_FAILURE(status))
                return status;
 
@@ -1006,7 +1062,7 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
                return AE_ERROR;
        }
        if (obj->buffer.length != 8) {
-               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+               pr_warn("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return AE_ERROR;
        }
@@ -1015,18 +1071,16 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
        kfree(obj);
 
        if (return_value.error_code || return_value.ec_return_value) {
-               pr_warning("Get Current Device Status failed: "
-                       "0x%x - 0x%x\n", return_value.error_code,
+               pr_warn("Get Current Device Status failed: 0x%x - 0x%x\n",
+                       return_value.error_code,
                        return_value.ec_return_value);
                return status;
        }
 
        devices = return_value.devices;
-       params.function_num = 0x2;
-       params.hotkey_number = 0x01;
-       params.devices = (value) ? (devices | device) : (devices & ~device);
+       set_params.devices = (value) ? (devices | device) : (devices & ~device);
 
-       status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
+       status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &set_input, &output2);
        if (ACPI_FAILURE(status))
                return status;
 
@@ -1039,7 +1093,7 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
                return AE_ERROR;
        }
        if (obj->buffer.length != 4) {
-               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+               pr_warn("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return AE_ERROR;
        }
@@ -1048,8 +1102,8 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
        kfree(obj);
 
        if (return_value.error_code || return_value.ec_return_value)
-               pr_warning("Set Device Status failed: "
-                       "0x%x - 0x%x\n", return_value.error_code,
+               pr_warn("Set Device Status failed: 0x%x - 0x%x\n",
+                       return_value.error_code,
                        return_value.ec_return_value);
 
        return status;
@@ -1096,6 +1150,8 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
                interface->capability |= ACER_CAP_THREEG;
        if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
                interface->capability |= ACER_CAP_BLUETOOTH;
+
+       commun_fn_key_number = type_aa->commun_fn_key_number;
 }
 
 static acpi_status WMID_set_capabilities(void)
@@ -1154,15 +1210,15 @@ static acpi_status get_u32(u32 *value, u32 cap)
 
        switch (interface->type) {
        case ACER_AMW0:
-               status = AMW0_get_u32(value, cap, interface);
+               status = AMW0_get_u32(value, cap);
                break;
        case ACER_AMW0_V2:
                if (cap == ACER_CAP_MAILLED) {
-                       status = AMW0_get_u32(value, cap, interface);
+                       status = AMW0_get_u32(value, cap);
                        break;
                }
        case ACER_WMID:
-               status = WMID_get_u32(value, cap, interface);
+               status = WMID_get_u32(value, cap);
                break;
        case ACER_WMID_v2:
                if (cap & (ACER_CAP_WIRELESS |
@@ -1170,7 +1226,7 @@ static acpi_status get_u32(u32 *value, u32 cap)
                           ACER_CAP_THREEG))
                        status = wmid_v2_get_u32(value, cap);
                else if (wmi_has_guid(WMID_GUID2))
-                       status = WMID_get_u32(value, cap, interface);
+                       status = WMID_get_u32(value, cap);
                break;
        }
 
@@ -1184,10 +1240,10 @@ static acpi_status set_u32(u32 value, u32 cap)
        if (interface->capability & cap) {
                switch (interface->type) {
                case ACER_AMW0:
-                       return AMW0_set_u32(value, cap, interface);
+                       return AMW0_set_u32(value, cap);
                case ACER_AMW0_V2:
                        if (cap == ACER_CAP_MAILLED)
-                               return AMW0_set_u32(value, cap, interface);
+                               return AMW0_set_u32(value, cap);
 
                        /*
                         * On some models, some WMID methods don't toggle
@@ -1197,21 +1253,21 @@ static acpi_status set_u32(u32 value, u32 cap)
                         */
                        if (cap == ACER_CAP_WIRELESS ||
                                cap == ACER_CAP_BLUETOOTH) {
-                               status = WMID_set_u32(value, cap, interface);
+                               status = WMID_set_u32(value, cap);
                                if (ACPI_FAILURE(status))
                                        return status;
 
-                               return AMW0_set_u32(value, cap, interface);
+                               return AMW0_set_u32(value, cap);
                        }
                case ACER_WMID:
-                       return WMID_set_u32(value, cap, interface);
+                       return WMID_set_u32(value, cap);
                case ACER_WMID_v2:
                        if (cap & (ACER_CAP_WIRELESS |
                                   ACER_CAP_BLUETOOTH |
                                   ACER_CAP_THREEG))
                                return wmid_v2_set_u32(value, cap);
                        else if (wmi_has_guid(WMID_GUID2))
-                               return WMID_set_u32(value, cap, interface);
+                               return WMID_set_u32(value, cap);
                default:
                        return AE_BAD_PARAMETER;
                }
@@ -1488,8 +1544,8 @@ static ssize_t show_bool_threeg(struct device *dev,
        u32 result; \
        acpi_status status;
 
-       pr_info("This threeg sysfs will be removed in 2012"
-               " - used by: %s\n", current->comm);
+       pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
+               current->comm);
        status = get_u32(&result, ACER_CAP_THREEG);
        if (ACPI_SUCCESS(status))
                return sprintf(buf, "%u\n", result);
@@ -1501,8 +1557,8 @@ static ssize_t set_bool_threeg(struct device *dev,
 {
        u32 tmp = simple_strtoul(buf, NULL, 10);
        acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
-       pr_info("This threeg sysfs will be removed in 2012"
-               " - used by: %s\n", current->comm);
+       pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
+               current->comm);
        if (ACPI_FAILURE(status))
                return -EINVAL;
        return count;
@@ -1513,8 +1569,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
        char *buf)
 {
-       pr_info("This interface sysfs will be removed in 2012"
-               " - used by: %s\n", current->comm);
+       pr_info("This interface sysfs will be removed in 2012 - used by: %s\n",
+               current->comm);
        switch (interface->type) {
        case ACER_AMW0:
                return sprintf(buf, "AMW0\n");
@@ -1981,9 +2037,13 @@ static int __init acer_wmi_init(void)
        set_quirks();
 
        if (acpi_video_backlight_support()) {
-               interface->capability &= ~ACER_CAP_BRIGHTNESS;
-               pr_info("Brightness must be controlled by "
-                      "generic video driver\n");
+               if (dmi_check_system(video_vendor_dmi_table)) {
+                       acpi_video_unregister();
+               } else {
+                       interface->capability &= ~ACER_CAP_BRIGHTNESS;
+                       pr_info("Brightness must be controlled by "
+                               "acpi video driver\n");
+               }
        }
 
        if (wmi_has_guid(WMID_GUID3)) {
@@ -2008,7 +2068,7 @@ static int __init acer_wmi_init(void)
 
        err = platform_driver_register(&acer_platform_driver);
        if (err) {
-               pr_err("Unable to register platform driver.\n");
+               pr_err("Unable to register platform driver\n");
                goto error_platform_register;
        }
 
index 760c6d7624fe505f5da3f40060a1df9d0eaf12b0..bc8384c6f3ebe889d10678fe6147214c3b56858d 100644 (file)
@@ -244,12 +244,11 @@ static void acerhdf_change_fanstate(int state)
        unsigned char cmd;
 
        if (verbose)
-               pr_notice("fan %s\n", (state == ACERHDF_FAN_OFF) ?
-                               "OFF" : "ON");
+               pr_notice("fan %s\n", state == ACERHDF_FAN_OFF ? "OFF" : "ON");
 
        if ((state != ACERHDF_FAN_OFF) && (state != ACERHDF_FAN_AUTO)) {
                pr_err("invalid fan state %d requested, setting to auto!\n",
-                       state);
+                      state);
                state = ACERHDF_FAN_AUTO;
        }
 
@@ -264,19 +263,18 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
 {
        if (fanon > ACERHDF_MAX_FANON) {
                pr_err("fanon temperature too high, set to %d\n",
-                               ACERHDF_MAX_FANON);
+                      ACERHDF_MAX_FANON);
                fanon = ACERHDF_MAX_FANON;
        }
 
        if (kernelmode && prev_interval != interval) {
                if (interval > ACERHDF_MAX_INTERVAL) {
                        pr_err("interval too high, set to %d\n",
-                               ACERHDF_MAX_INTERVAL);
+                              ACERHDF_MAX_INTERVAL);
                        interval = ACERHDF_MAX_INTERVAL;
                }
                if (verbose)
-                       pr_notice("interval changed to: %d\n",
-                                       interval);
+                       pr_notice("interval changed to: %d\n", interval);
                thermal->polling_delay = interval*1000;
                prev_interval = interval;
        }
@@ -587,8 +585,8 @@ static int acerhdf_check_hardware(void)
        }
 
        if (!bios_cfg) {
-               pr_err("unknown (unsupported) BIOS version %s/%s/%s, "
-                       "please report, aborting!\n", vendor, product, version);
+               pr_err("unknown (unsupported) BIOS version %s/%s/%s, please report, aborting!\n",
+                      vendor, product, version);
                return -EINVAL;
        }
 
@@ -598,8 +596,7 @@ static int acerhdf_check_hardware(void)
         */
        if (!kernelmode) {
                pr_notice("Fan control off, to enable do:\n");
-               pr_notice("echo -n \"enabled\" > "
-                       "/sys/class/thermal/thermal_zone0/mode\n");
+               pr_notice("echo -n \"enabled\" > /sys/class/thermal/thermal_zone0/mode\n");
        }
 
        return 0;
index 19170bb7700b0f9307b1472868f3ca7799ad03b1..a514bf66fdd7e2a6532fd5be9a97f6aa2a417fb6 100644 (file)
@@ -97,9 +97,12 @@ static struct rfkill *amilo_rfkill_dev;
 
 static int __devinit amilo_rfkill_probe(struct platform_device *device)
 {
+       int rc;
        const struct dmi_system_id *system_id =
                dmi_first_match(amilo_rfkill_id_table);
-       int rc;
+
+       if (!system_id)
+               return -ENXIO;
 
        amilo_rfkill_dev = rfkill_alloc(KBUILD_MODNAME, &device->dev,
                                        RFKILL_TYPE_WLAN,
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
new file mode 100644 (file)
index 0000000..8a582bd
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ *  Gmux driver for Apple laptops
+ *
+ *  Copyright (C) Canonical Ltd. <seth.forshee@canonical.com>
+ *
+ *  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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/backlight.h>
+#include <linux/acpi.h>
+#include <linux/pnp.h>
+#include <linux/apple_bl.h>
+#include <linux/slab.h>
+#include <acpi/video.h>
+#include <asm/io.h>
+
+struct apple_gmux_data {
+       unsigned long iostart;
+       unsigned long iolen;
+
+       struct backlight_device *bdev;
+};
+
+/*
+ * gmux port offsets. Many of these are not yet used, but may be in the
+ * future, and it's useful to have them documented here anyhow.
+ */
+#define GMUX_PORT_VERSION_MAJOR                0x04
+#define GMUX_PORT_VERSION_MINOR                0x05
+#define GMUX_PORT_VERSION_RELEASE      0x06
+#define GMUX_PORT_SWITCH_DISPLAY       0x10
+#define GMUX_PORT_SWITCH_GET_DISPLAY   0x11
+#define GMUX_PORT_INTERRUPT_ENABLE     0x14
+#define GMUX_PORT_INTERRUPT_STATUS     0x16
+#define GMUX_PORT_SWITCH_DDC           0x28
+#define GMUX_PORT_SWITCH_EXTERNAL      0x40
+#define GMUX_PORT_SWITCH_GET_EXTERNAL  0x41
+#define GMUX_PORT_DISCRETE_POWER       0x50
+#define GMUX_PORT_MAX_BRIGHTNESS       0x70
+#define GMUX_PORT_BRIGHTNESS           0x74
+
+#define GMUX_MIN_IO_LEN                        (GMUX_PORT_BRIGHTNESS + 4)
+
+#define GMUX_INTERRUPT_ENABLE          0xff
+#define GMUX_INTERRUPT_DISABLE         0x00
+
+#define GMUX_INTERRUPT_STATUS_ACTIVE   0
+#define GMUX_INTERRUPT_STATUS_DISPLAY  (1 << 0)
+#define GMUX_INTERRUPT_STATUS_POWER    (1 << 2)
+#define GMUX_INTERRUPT_STATUS_HOTPLUG  (1 << 3)
+
+#define GMUX_BRIGHTNESS_MASK           0x00ffffff
+#define GMUX_MAX_BRIGHTNESS            GMUX_BRIGHTNESS_MASK
+
+static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port)
+{
+       return inb(gmux_data->iostart + port);
+}
+
+static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port,
+                              u8 val)
+{
+       outb(val, gmux_data->iostart + port);
+}
+
+static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port)
+{
+       return inl(gmux_data->iostart + port);
+}
+
+static int gmux_get_brightness(struct backlight_device *bd)
+{
+       struct apple_gmux_data *gmux_data = bl_get_data(bd);
+       return gmux_read32(gmux_data, GMUX_PORT_BRIGHTNESS) &
+              GMUX_BRIGHTNESS_MASK;
+}
+
+static int gmux_update_status(struct backlight_device *bd)
+{
+       struct apple_gmux_data *gmux_data = bl_get_data(bd);
+       u32 brightness = bd->props.brightness;
+
+       /*
+        * Older gmux versions require writing out lower bytes first then
+        * setting the upper byte to 0 to flush the values. Newer versions
+        * accept a single u32 write, but the old method also works, so we
+        * just use the old method for all gmux versions.
+        */
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness);
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8);
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16);
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0);
+
+       return 0;
+}
+
+static const struct backlight_ops gmux_bl_ops = {
+       .get_brightness = gmux_get_brightness,
+       .update_status = gmux_update_status,
+};
+
+static int __devinit gmux_probe(struct pnp_dev *pnp,
+                               const struct pnp_device_id *id)
+{
+       struct apple_gmux_data *gmux_data;
+       struct resource *res;
+       struct backlight_properties props;
+       struct backlight_device *bdev;
+       u8 ver_major, ver_minor, ver_release;
+       int ret = -ENXIO;
+
+       gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL);
+       if (!gmux_data)
+               return -ENOMEM;
+       pnp_set_drvdata(pnp, gmux_data);
+
+       res = pnp_get_resource(pnp, IORESOURCE_IO, 0);
+       if (!res) {
+               pr_err("Failed to find gmux I/O resource\n");
+               goto err_free;
+       }
+
+       gmux_data->iostart = res->start;
+       gmux_data->iolen = res->end - res->start;
+
+       if (gmux_data->iolen < GMUX_MIN_IO_LEN) {
+               pr_err("gmux I/O region too small (%lu < %u)\n",
+                      gmux_data->iolen, GMUX_MIN_IO_LEN);
+               goto err_free;
+       }
+
+       if (!request_region(gmux_data->iostart, gmux_data->iolen,
+                           "Apple gmux")) {
+               pr_err("gmux I/O already in use\n");
+               goto err_free;
+       }
+
+       /*
+        * On some machines the gmux is in ACPI even thought the machine
+        * doesn't really have a gmux. Check for invalid version information
+        * to detect this.
+        */
+       ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
+       ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
+       ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
+       if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
+               pr_info("gmux device not present\n");
+               ret = -ENODEV;
+               goto err_release;
+       }
+
+       pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor,
+               ver_release);
+
+       memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
+
+       /*
+        * Currently it's assumed that the maximum brightness is less than
+        * 2^24 for compatibility with old gmux versions. Cap the max
+        * brightness at this value, but print a warning if the hardware
+        * reports something higher so that it can be fixed.
+        */
+       if (WARN_ON(props.max_brightness > GMUX_MAX_BRIGHTNESS))
+               props.max_brightness = GMUX_MAX_BRIGHTNESS;
+
+       bdev = backlight_device_register("gmux_backlight", &pnp->dev,
+                                        gmux_data, &gmux_bl_ops, &props);
+       if (IS_ERR(bdev)) {
+               ret = PTR_ERR(bdev);
+               goto err_release;
+       }
+
+       gmux_data->bdev = bdev;
+       bdev->props.brightness = gmux_get_brightness(bdev);
+       backlight_update_status(bdev);
+
+       /*
+        * The backlight situation on Macs is complicated. If the gmux is
+        * present it's the best choice, because it always works for
+        * backlight control and supports more levels than other options.
+        * Disable the other backlight choices.
+        */
+       acpi_video_unregister();
+       apple_bl_unregister();
+
+       return 0;
+
+err_release:
+       release_region(gmux_data->iostart, gmux_data->iolen);
+err_free:
+       kfree(gmux_data);
+       return ret;
+}
+
+static void __devexit gmux_remove(struct pnp_dev *pnp)
+{
+       struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
+
+       backlight_device_unregister(gmux_data->bdev);
+       release_region(gmux_data->iostart, gmux_data->iolen);
+       kfree(gmux_data);
+
+       acpi_video_register();
+       apple_bl_register();
+}
+
+static const struct pnp_device_id gmux_device_ids[] = {
+       {"APP000B", 0},
+       {"", 0}
+};
+
+static struct pnp_driver gmux_pnp_driver = {
+       .name           = "apple-gmux",
+       .probe          = gmux_probe,
+       .remove         = __devexit_p(gmux_remove),
+       .id_table       = gmux_device_ids,
+};
+
+static int __init apple_gmux_init(void)
+{
+       return pnp_register_driver(&gmux_pnp_driver);
+}
+
+static void __exit apple_gmux_exit(void)
+{
+       pnp_unregister_driver(&gmux_pnp_driver);
+}
+
+module_init(apple_gmux_init);
+module_exit(apple_gmux_exit);
+
+MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>");
+MODULE_DESCRIPTION("Apple Gmux Driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pnp, gmux_device_ids);
index b7944f9038866f2e50ba3c84604e2e7dea7f55b0..e38f91be0b10964c12f6a9b8eb4347908fc54d94 100644 (file)
@@ -81,6 +81,19 @@ static uint wapf = 1;
 module_param(wapf, uint, 0444);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
+static char *wled_type = "unknown";
+static char *bled_type = "unknown";
+
+module_param(wled_type, charp, 0444);
+MODULE_PARM_DESC(wlan_status, "Set the wled type on boot "
+                "(unknown, led or rfkill). "
+                "default is unknown");
+
+module_param(bled_type, charp, 0444);
+MODULE_PARM_DESC(bled_type, "Set the bled type on boot "
+                "(unknown, led or rfkill). "
+                "default is unknown");
+
 static int wlan_status = 1;
 static int bluetooth_status = 1;
 static int wimax_status = -1;
@@ -137,6 +150,11 @@ MODULE_PARM_DESC(als_status, "Set the ALS status on boot "
 #define WM_RSTS                0x08    /* internal wimax */
 #define WW_RSTS                0x20    /* internal wwan */
 
+/* WLED and BLED type */
+#define TYPE_UNKNOWN   0
+#define TYPE_LED       1
+#define TYPE_RFKILL    2
+
 /* LED */
 #define METHOD_MLED            "MLED"
 #define METHOD_TLED            "TLED"
@@ -218,8 +236,9 @@ struct asus_led {
 /*
  * Same thing for rfkill
  */
-struct asus_pega_rfkill {
-       int control_id;         /* type of control. Maps to PEGA_* values */
+struct asus_rfkill {
+       /* type of control. Maps to PEGA_* values or *_RSTS  */
+       int control_id;
        struct rfkill *rfkill;
        struct asus_laptop *asus;
 };
@@ -240,6 +259,8 @@ struct asus_laptop {
        struct key_entry *keymap;
        struct input_polled_dev *pega_accel_poll;
 
+       struct asus_led wled;
+       struct asus_led bled;
        struct asus_led mled;
        struct asus_led tled;
        struct asus_led rled;
@@ -248,6 +269,8 @@ struct asus_laptop {
        struct asus_led kled;
        struct workqueue_struct *led_workqueue;
 
+       int wled_type;
+       int bled_type;
        int wireless_status;
        bool have_rsts;
        bool is_pega_lucid;
@@ -256,11 +279,11 @@ struct asus_laptop {
        int pega_acc_y;
        int pega_acc_z;
 
-       struct rfkill *gps_rfkill;
-
-       struct asus_pega_rfkill wlanrfk;
-       struct asus_pega_rfkill btrfk;
-       struct asus_pega_rfkill wwanrfk;
+       struct asus_rfkill wlan;
+       struct asus_rfkill bluetooth;
+       struct asus_rfkill wwan;
+       struct asus_rfkill wimax;
+       struct asus_rfkill gps;
 
        acpi_handle handle;     /* the handle of the hotk device */
        u32 ledd_status;        /* status of the LED display */
@@ -274,6 +297,7 @@ static const struct key_entry asus_keymap[] = {
        {KE_KEY, 0x02, { KEY_SCREENLOCK } },
        {KE_KEY, 0x05, { KEY_WLAN } },
        {KE_KEY, 0x08, { KEY_F13 } },
+       {KE_KEY, 0x09, { KEY_PROG2 } }, /* Dock */
        {KE_KEY, 0x17, { KEY_ZOOM } },
        {KE_KEY, 0x1f, { KEY_BATTERY } },
        /* End of Lenovo SL Specific keycodes */
@@ -299,6 +323,8 @@ static const struct key_entry asus_keymap[] = {
        {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
        {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
        {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
+       {KE_KEY, 0x6C, { KEY_SLEEP } }, /* Suspend */
+       {KE_KEY, 0x6D, { KEY_SLEEP } }, /* Hibernate */
        {KE_KEY, 0x7E, { KEY_BLUETOOTH } },
        {KE_KEY, 0x7D, { KEY_BLUETOOTH } },
        {KE_KEY, 0x82, { KEY_CAMERA } },
@@ -601,6 +627,10 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
 
 static void asus_led_exit(struct asus_laptop *asus)
 {
+       if (!IS_ERR_OR_NULL(asus->wled.led.dev))
+               led_classdev_unregister(&asus->wled.led);
+       if (!IS_ERR_OR_NULL(asus->bled.led.dev))
+               led_classdev_unregister(&asus->bled.led);
        if (!IS_ERR_OR_NULL(asus->mled.led.dev))
                led_classdev_unregister(&asus->mled.led);
        if (!IS_ERR_OR_NULL(asus->tled.led.dev))
@@ -642,7 +672,7 @@ static int asus_led_register(struct asus_laptop *asus,
 
 static int asus_led_init(struct asus_laptop *asus)
 {
-       int r;
+       int r = 0;
 
        /*
         * The Pegatron Lucid has no physical leds, but all methods are
@@ -661,6 +691,16 @@ static int asus_led_init(struct asus_laptop *asus)
        if (!asus->led_workqueue)
                return -ENOMEM;
 
+       if (asus->wled_type == TYPE_LED)
+               r = asus_led_register(asus, &asus->wled, "asus::wlan",
+                                     METHOD_WLAN);
+       if (r)
+               goto error;
+       if (asus->bled_type == TYPE_LED)
+               r = asus_led_register(asus, &asus->bled, "asus::bluetooth",
+                                     METHOD_BLUETOOTH);
+       if (r)
+               goto error;
        r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED);
        if (r)
                goto error;
@@ -963,7 +1003,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
        return sysfs_acpi_set(asus, buf, count, METHOD_WLAN);
 }
 
-/*
+/*e
  * Bluetooth
  */
 static int asus_bluetooth_set(struct asus_laptop *asus, int status)
@@ -1228,7 +1268,7 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
        ret = asus_gps_switch(asus, !!value);
        if (ret)
                return ret;
-       rfkill_set_sw_state(asus->gps_rfkill, !value);
+       rfkill_set_sw_state(asus->gps.rfkill, !value);
        return rv;
 }
 
@@ -1246,90 +1286,139 @@ static const struct rfkill_ops asus_gps_rfkill_ops = {
        .set_block = asus_gps_rfkill_set,
 };
 
+static int asus_rfkill_set(void *data, bool blocked)
+{
+       struct asus_rfkill *rfk = data;
+       struct asus_laptop *asus = rfk->asus;
+
+       if (rfk->control_id == WL_RSTS)
+               return asus_wlan_set(asus, !blocked);
+       else if (rfk->control_id == BT_RSTS)
+               return asus_bluetooth_set(asus, !blocked);
+       else if (rfk->control_id == WM_RSTS)
+               return asus_wimax_set(asus, !blocked);
+       else if (rfk->control_id == WW_RSTS)
+               return asus_wwan_set(asus, !blocked);
+
+       return -EINVAL;
+}
+
+static const struct rfkill_ops asus_rfkill_ops = {
+       .set_block = asus_rfkill_set,
+};
+
+static void asus_rfkill_terminate(struct asus_rfkill *rfk)
+{
+       if (!rfk->rfkill)
+               return ;
+
+       rfkill_unregister(rfk->rfkill);
+       rfkill_destroy(rfk->rfkill);
+       rfk->rfkill = NULL;
+}
+
 static void asus_rfkill_exit(struct asus_laptop *asus)
 {
-       if (asus->gps_rfkill) {
-               rfkill_unregister(asus->gps_rfkill);
-               rfkill_destroy(asus->gps_rfkill);
-               asus->gps_rfkill = NULL;
-       }
+       asus_rfkill_terminate(&asus->wwan);
+       asus_rfkill_terminate(&asus->bluetooth);
+       asus_rfkill_terminate(&asus->wlan);
+       asus_rfkill_terminate(&asus->gps);
 }
 
-static int asus_rfkill_init(struct asus_laptop *asus)
+static int asus_rfkill_setup(struct asus_laptop *asus, struct asus_rfkill *rfk,
+                            const char *name, int control_id, int type,
+                            const struct rfkill_ops *ops)
 {
        int result;
 
-       if (acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) ||
-           acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) ||
-           acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
-               return 0;
-
-       asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
-                                       RFKILL_TYPE_GPS,
-                                       &asus_gps_rfkill_ops, asus);
-       if (!asus->gps_rfkill)
+       rfk->control_id = control_id;
+       rfk->asus = asus;
+       rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
+                                  type, ops, rfk);
+       if (!rfk->rfkill)
                return -EINVAL;
 
-       result = rfkill_register(asus->gps_rfkill);
+       result = rfkill_register(rfk->rfkill);
        if (result) {
-               rfkill_destroy(asus->gps_rfkill);
-               asus->gps_rfkill = NULL;
+               rfkill_destroy(rfk->rfkill);
+               rfk->rfkill = NULL;
        }
 
        return result;
 }
 
-static int pega_rfkill_set(void *data, bool blocked)
+static int asus_rfkill_init(struct asus_laptop *asus)
 {
-       struct asus_pega_rfkill *pega_rfk = data;
+       int result = 0;
 
-       int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
-       pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);
+       if (asus->is_pega_lucid)
+               return -ENODEV;
 
-       return ret;
-}
+       if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
+           !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
+           !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
+               result = asus_rfkill_setup(asus, &asus->gps, "asus-gps",
+                                          -1, RFKILL_TYPE_GPS,
+                                          &asus_gps_rfkill_ops);
+       if (result)
+               goto exit;
 
-static const struct rfkill_ops pega_rfkill_ops = {
-       .set_block = pega_rfkill_set,
-};
 
-static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
-{
-       pr_warn("Terminating %d\n", pega_rfk->control_id);
-       if (pega_rfk->rfkill) {
-               rfkill_unregister(pega_rfk->rfkill);
-               rfkill_destroy(pega_rfk->rfkill);
-               pega_rfk->rfkill = NULL;
-       }
-}
+       if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL) &&
+           asus->wled_type == TYPE_RFKILL)
+               result = asus_rfkill_setup(asus, &asus->wlan, "asus-wlan",
+                                          WL_RSTS, RFKILL_TYPE_WLAN,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
 
-static void pega_rfkill_exit(struct asus_laptop *asus)
-{
-       pega_rfkill_terminate(&asus->wwanrfk);
-       pega_rfkill_terminate(&asus->btrfk);
-       pega_rfkill_terminate(&asus->wlanrfk);
+       if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL) &&
+           asus->bled_type == TYPE_RFKILL)
+               result = asus_rfkill_setup(asus, &asus->bluetooth,
+                                          "asus-bluetooth", BT_RSTS,
+                                          RFKILL_TYPE_BLUETOOTH,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
+
+       if (!acpi_check_handle(asus->handle, METHOD_WWAN, NULL))
+               result = asus_rfkill_setup(asus, &asus->wwan, "asus-wwan",
+                                          WW_RSTS, RFKILL_TYPE_WWAN,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
+
+       if (!acpi_check_handle(asus->handle, METHOD_WIMAX, NULL))
+               result = asus_rfkill_setup(asus, &asus->wimax, "asus-wimax",
+                                          WM_RSTS, RFKILL_TYPE_WIMAX,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
+
+exit:
+       if (result)
+               asus_rfkill_exit(asus);
+
+       return result;
 }
 
-static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
-               const char *name, int controlid, int rfkill_type)
+static int pega_rfkill_set(void *data, bool blocked)
 {
-       int result;
+       struct asus_rfkill *rfk = data;
 
-       pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
-       pega_rfk->control_id = controlid;
-       pega_rfk->asus = asus;
-       pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
-                                       rfkill_type, &pega_rfkill_ops, pega_rfk);
-       if (!pega_rfk->rfkill)
-               return -EINVAL;
+       int ret = asus_pega_lucid_set(rfk->asus, rfk->control_id, !blocked);
+       return ret;
+}
 
-       result = rfkill_register(pega_rfk->rfkill);
-       if (result) {
-               rfkill_destroy(pega_rfk->rfkill);
-               pega_rfk->rfkill = NULL;
-       }
+static const struct rfkill_ops pega_rfkill_ops = {
+       .set_block = pega_rfkill_set,
+};
 
-       return result;
+static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_rfkill *rfk,
+                            const char *name, int controlid, int rfkill_type)
+{
+       return asus_rfkill_setup(asus, rfk, name, controlid, rfkill_type,
+                                &pega_rfkill_ops);
 }
 
 static int pega_rfkill_init(struct asus_laptop *asus)
@@ -1339,22 +1428,22 @@ static int pega_rfkill_init(struct asus_laptop *asus)
        if(!asus->is_pega_lucid)
                return -ENODEV;
 
-       ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
-       if(ret)
-               return ret;
-       ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
+       ret = pega_rfkill_setup(asus, &asus->wlan, "pega-wlan",
+                               PEGA_WLAN, RFKILL_TYPE_WLAN);
        if(ret)
-               goto err_btrfk;
-       ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
+               goto exit;
+
+       ret = pega_rfkill_setup(asus, &asus->bluetooth, "pega-bt",
+                               PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
        if(ret)
-               goto err_wwanrfk;
+               goto exit;
 
-       pr_warn("Pega rfkill init succeeded\n");
-       return 0;
-err_wwanrfk:
-       pega_rfkill_terminate(&asus->btrfk);
-err_btrfk:
-       pega_rfkill_terminate(&asus->wlanrfk);
+       ret = pega_rfkill_setup(asus, &asus->wwan, "pega-wwan",
+                               PEGA_WWAN, RFKILL_TYPE_WWAN);
+
+exit:
+       if (ret)
+               asus_rfkill_exit(asus);
 
        return ret;
 }
@@ -1364,8 +1453,10 @@ err_btrfk:
  */
 static void asus_input_notify(struct asus_laptop *asus, int event)
 {
-       if (asus->inputdev)
-               sparse_keymap_report_event(asus->inputdev, event, 1, true);
+       if (!asus->inputdev)
+               return ;
+       if (!sparse_keymap_report_event(asus->inputdev, event, 1, true))
+               pr_info("Unknown key %x pressed\n", event);
 }
 
 static int asus_input_init(struct asus_laptop *asus)
@@ -1375,7 +1466,7 @@ static int asus_input_init(struct asus_laptop *asus)
 
        input = input_allocate_device();
        if (!input) {
-               pr_info("Unable to allocate input device\n");
+               pr_warn("Unable to allocate input device\n");
                return -ENOMEM;
        }
        input->name = "Asus Laptop extra buttons";
@@ -1390,7 +1481,7 @@ static int asus_input_init(struct asus_laptop *asus)
        }
        error = input_register_device(input);
        if (error) {
-               pr_info("Unable to register input device\n");
+               pr_warn("Unable to register input device\n");
                goto err_free_keymap;
        }
 
@@ -1688,7 +1779,16 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
        if (result)
                return result;
 
-       /* WLED and BLED are on by default */
+       if (!strcmp(bled_type, "led"))
+               asus->bled_type = TYPE_LED;
+       else if (!strcmp(bled_type, "rfkill"))
+               asus->bled_type = TYPE_RFKILL;
+
+       if (!strcmp(wled_type, "led"))
+               asus->wled_type = TYPE_LED;
+       else if (!strcmp(wled_type, "rfkill"))
+               asus->wled_type = TYPE_RFKILL;
+
        if (bluetooth_status >= 0)
                asus_bluetooth_set(asus, !!bluetooth_status);
 
@@ -1786,7 +1886,7 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
                goto fail_led;
 
        result = asus_rfkill_init(asus);
-       if (result)
+       if (result && result != -ENODEV)
                goto fail_rfkill;
 
        result = pega_accel_init(asus);
@@ -1828,7 +1928,6 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
        asus_led_exit(asus);
        asus_input_exit(asus);
        pega_accel_exit(asus);
-       pega_rfkill_exit(asus);
        asus_platform_exit(asus);
 
        kfree(asus->name);
index b0859d4183e8307d27ef9c3979bf613d4548c603..99a30b513137c50fe5224318c55d5d081fdf8973 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/fb.h>
 
 #include "asus-wmi.h"
 
@@ -51,9 +52,14 @@ static uint wapf;
 module_param(wapf, uint, 0444);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
+static struct quirk_entry quirk_asus_unknown = {
+};
+
 static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
 {
-       driver->wapf = wapf;
+       driver->quirks = &quirk_asus_unknown;
+       driver->quirks->wapf = wapf;
+       driver->panel_power = FB_BLANK_UNBLANK;
 }
 
 static const struct key_entry asus_nb_wmi_keymap[] = {
@@ -70,6 +76,8 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x50, { KEY_EMAIL } },
        { KE_KEY, 0x51, { KEY_WWW } },
        { KE_KEY, 0x55, { KEY_CALC } },
+       { KE_IGNORE, 0x57, },  /* Battery mode */
+       { KE_IGNORE, 0x58, },  /* AC mode */
        { KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
        { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
        { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
@@ -99,7 +107,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
        .keymap = asus_nb_wmi_keymap,
        .input_name = "Asus WMI hotkeys",
        .input_phys = ASUS_NB_WMI_FILE "/input0",
-       .quirks = asus_nb_wmi_quirks,
+       .detect_quirks = asus_nb_wmi_quirks,
 };
 
 
index 9929246895deb386a75dd08b00722f0424257595..77aadde5281c97ae423e35f5255c7e9b63d36b70 100644 (file)
@@ -411,7 +411,7 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
 
        if (retval >= 0) {
                if (level)
-                       *level = retval & 0x80 ? retval & 0x7F : 0;
+                       *level = retval & 0x7F;
                if (env)
                        *env = (retval >> 8) & 0x7F;
                retval = 0;
@@ -784,7 +784,8 @@ static int asus_new_rfkill(struct asus_wmi *asus,
        arfkill->dev_id = dev_id;
        arfkill->asus = asus;
 
-       if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
+       if (dev_id == ASUS_WMI_DEVID_WLAN &&
+           asus->driver->quirks->hotplug_wireless)
                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
                                       &asus_rfkill_wlan_ops, arfkill);
        else
@@ -895,7 +896,7 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
        if (result && result != -ENODEV)
                goto exit;
 
-       if (!asus->driver->hotplug_wireless)
+       if (!asus->driver->quirks->hotplug_wireless)
                goto exit;
 
        result = asus_setup_pci_hotplug(asus);
@@ -1075,7 +1076,12 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
  */
 static int read_backlight_power(struct asus_wmi *asus)
 {
-       int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
+       int ret;
+       if (asus->driver->quirks->store_backlight_power)
+               ret = !asus->driver->panel_power;
+       else
+               ret = asus_wmi_get_devstate_simple(asus,
+                                                  ASUS_WMI_DEVID_BACKLIGHT);
 
        if (ret < 0)
                return ret;
@@ -1116,26 +1122,51 @@ static int read_brightness(struct backlight_device *bd)
        return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
 }
 
-static int update_bl_status(struct backlight_device *bd)
+static u32 get_scalar_command(struct backlight_device *bd)
 {
        struct asus_wmi *asus = bl_get_data(bd);
-       u32 ctrl_param;
-       int power, err;
+       u32 ctrl_param = 0;
 
-       ctrl_param = bd->props.brightness;
+       if ((asus->driver->brightness < bd->props.brightness) ||
+           bd->props.brightness == bd->props.max_brightness)
+               ctrl_param = 0x00008001;
+       else if ((asus->driver->brightness > bd->props.brightness) ||
+                bd->props.brightness == 0)
+               ctrl_param = 0x00008000;
 
-       err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
-                                   ctrl_param, NULL);
+       asus->driver->brightness = bd->props.brightness;
 
-       if (err < 0)
-               return err;
+       return ctrl_param;
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+       struct asus_wmi *asus = bl_get_data(bd);
+       u32 ctrl_param;
+       int power, err = 0;
 
        power = read_backlight_power(asus);
        if (power != -ENODEV && bd->props.power != power) {
                ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
                err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
                                            ctrl_param, NULL);
+               if (asus->driver->quirks->store_backlight_power)
+                       asus->driver->panel_power = bd->props.power;
+
+               /* When using scalar brightness, updating the brightness
+                * will mess with the backlight power */
+               if (asus->driver->quirks->scalar_panel_brightness)
+                       return err;
        }
+
+       if (asus->driver->quirks->scalar_panel_brightness)
+               ctrl_param = get_scalar_command(bd);
+       else
+               ctrl_param = bd->props.brightness;
+
+       err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
+                                   ctrl_param, NULL);
+
        return err;
 }
 
@@ -1196,10 +1227,15 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
 
        asus->backlight_device = bd;
 
+       if (asus->driver->quirks->store_backlight_power)
+               asus->driver->panel_power = power;
+
        bd->props.brightness = read_brightness(bd);
        bd->props.power = power;
        backlight_update_status(bd);
 
+       asus->driver->brightness = bd->props.brightness;
+
        return 0;
 }
 
@@ -1441,9 +1477,9 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
 
        /* CWAP allow to define the behavior of the Fn+F2 key,
         * this method doesn't seems to be present on Eee PCs */
-       if (asus->driver->wapf >= 0)
+       if (asus->driver->quirks->wapf >= 0)
                asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
-                                     asus->driver->wapf, NULL);
+                                     asus->driver->quirks->wapf, NULL);
 
        return asus_wmi_sysfs_init(asus->platform_device);
 }
@@ -1622,8 +1658,8 @@ static int asus_wmi_add(struct platform_device *pdev)
        wdrv->platform_device = pdev;
        platform_set_drvdata(asus->platform_device, asus);
 
-       if (wdrv->quirks)
-               wdrv->quirks(asus->driver);
+       if (wdrv->detect_quirks)
+               wdrv->detect_quirks(asus->driver);
 
        err = asus_wmi_platform_init(asus);
        if (err)
index 8147c10161cc590d729c2afcfc03c43df7df3e1f..d43b66742004bae8cc0a819ca082a5e1065ef51f 100644 (file)
@@ -35,9 +35,16 @@ struct module;
 struct key_entry;
 struct asus_wmi;
 
+struct quirk_entry {
+       bool hotplug_wireless;
+       bool scalar_panel_brightness;
+       bool store_backlight_power;
+       int wapf;
+};
+
 struct asus_wmi_driver {
-       bool                    hotplug_wireless;
-       int                     wapf;
+       int                     brightness;
+       int                     panel_power;
 
        const char              *name;
        struct module           *owner;
@@ -47,13 +54,14 @@ struct asus_wmi_driver {
        const struct key_entry  *keymap;
        const char              *input_name;
        const char              *input_phys;
+       struct quirk_entry      *quirks;
        /* Returns new code, value, and autorelease values in arguments.
         * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
        void (*key_filter) (struct asus_wmi_driver *driver, int *code,
                            unsigned int *value, bool *autorelease);
 
        int (*probe) (struct platform_device *device);
-       void (*quirks) (struct asus_wmi_driver *driver);
+       void (*detect_quirks) (struct asus_wmi_driver *driver);
 
        struct platform_driver  platform_driver;
        struct platform_device *platform_device;
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
deleted file mode 100644 (file)
index 6f966d6..0000000
+++ /dev/null
@@ -1,1513 +0,0 @@
-/*
- *  asus_acpi.c - Asus Laptop ACPI Extras
- *
- *
- *  Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *  The development page for this driver is located at
- *  http://sourceforge.net/projects/acpi4asus/
- *
- *  Credits:
- *  Pontus Fuchs   - Helper functions, cleanup
- *  Johann Wiesner - Small compile fixes
- *  John Belmonte  - ACPI code for Toshiba laptop was a good starting point.
- *  ï¿½ic Burghard  - LED display support for W1N
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/backlight.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
-
-#define ASUS_ACPI_VERSION "0.30"
-
-#define PROC_ASUS       "asus" /* The directory */
-#define PROC_MLED       "mled"
-#define PROC_WLED       "wled"
-#define PROC_TLED       "tled"
-#define PROC_BT         "bluetooth"
-#define PROC_LEDD       "ledd"
-#define PROC_INFO       "info"
-#define PROC_LCD        "lcd"
-#define PROC_BRN        "brn"
-#define PROC_DISP       "disp"
-
-#define ACPI_HOTK_NAME          "Asus Laptop ACPI Extras Driver"
-#define ACPI_HOTK_CLASS         "hotkey"
-#define ACPI_HOTK_DEVICE_NAME   "Hotkey"
-
-/*
- * Some events we use, same for all Asus
- */
-#define BR_UP       0x10
-#define BR_DOWN     0x20
-
-/*
- * Flags for hotk status
- */
-#define MLED_ON     0x01       /* Mail LED */
-#define WLED_ON     0x02       /* Wireless LED */
-#define TLED_ON     0x04       /* Touchpad LED */
-#define BT_ON       0x08       /* Internal Bluetooth */
-
-MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
-MODULE_DESCRIPTION(ACPI_HOTK_NAME);
-MODULE_LICENSE("GPL");
-
-static uid_t asus_uid;
-static gid_t asus_gid;
-module_param(asus_uid, uint, 0);
-MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus");
-module_param(asus_gid, uint, 0);
-MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus");
-
-/* For each model, all features implemented,
- * those marked with R are relative to HOTK, A for absolute */
-struct model_data {
-       char *name;             /* name of the laptop________________A */
-       char *mt_mled;          /* method to handle mled_____________R */
-       char *mled_status;      /* node to handle mled reading_______A */
-       char *mt_wled;          /* method to handle wled_____________R */
-       char *wled_status;      /* node to handle wled reading_______A */
-       char *mt_tled;          /* method to handle tled_____________R */
-       char *tled_status;      /* node to handle tled reading_______A */
-       char *mt_ledd;          /* method to handle LED display______R */
-       char *mt_bt_switch;     /* method to switch Bluetooth on/off_R */
-       char *bt_status;        /* no model currently supports this__? */
-       char *mt_lcd_switch;    /* method to turn LCD on/off_________A */
-       char *lcd_status;       /* node to read LCD panel state______A */
-       char *brightness_up;    /* method to set brightness up_______A */
-       char *brightness_down;  /* method to set brightness down ____A */
-       char *brightness_set;   /* method to set absolute brightness_R */
-       char *brightness_get;   /* method to get absolute brightness_R */
-       char *brightness_status;/* node to get brightness____________A */
-       char *display_set;      /* method to set video output________R */
-       char *display_get;      /* method to get video output________R */
-};
-
-/*
- * This is the main structure, we can use it to store anything interesting
- * about the hotk device
- */
-struct asus_hotk {
-       struct acpi_device *device;     /* the device we are in */
-       acpi_handle handle;             /* the handle of the hotk device */
-       char status;                    /* status of the hotk, for LEDs */
-       u32 ledd_status;                /* status of the LED display */
-       struct model_data *methods;     /* methods available on the laptop */
-       u8 brightness;                  /* brightness level */
-       enum {
-               A1x = 0,        /* A1340D, A1300F */
-               A2x,            /* A2500H */
-               A4G,            /* A4700G */
-               D1x,            /* D1 */
-               L2D,            /* L2000D */
-               L3C,            /* L3800C */
-               L3D,            /* L3400D */
-               L3H,            /* L3H, L2000E, L5D */
-               L4R,            /* L4500R */
-               L5x,            /* L5800C */
-               L8L,            /* L8400L */
-               M1A,            /* M1300A */
-               M2E,            /* M2400E, L4400L */
-               M6N,            /* M6800N, W3400N */
-               M6R,            /* M6700R, A3000G */
-               P30,            /* Samsung P30 */
-               S1x,            /* S1300A, but also L1400B and M2400A (L84F) */
-               S2x,            /* S200 (J1 reported), Victor MP-XP7210 */
-               W1N,            /* W1000N */
-               W5A,            /* W5A */
-               W3V,            /* W3030V */
-               xxN,            /* M2400N, M3700N, M5200N, M6800N,
-                                                        S1300N, S5200N*/
-               A4S,            /* Z81sp */
-               F3Sa,           /* (Centrino) */
-               R1F,
-               END_MODEL
-       } model;                /* Models currently supported */
-       u16 event_count[128];   /* Count for each event TODO make this better */
-};
-
-/* Here we go */
-#define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."
-#define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."
-#define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
-#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."
-#define S1x_PREFIX "\\_SB.PCI0.PX40."
-#define S2x_PREFIX A1x_PREFIX
-#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
-
-static struct model_data model_conf[END_MODEL] = {
-       /*
-        * TODO I have seen a SWBX and AIBX method on some models, like L1400B,
-        * it seems to be a kind of switch, but what for ?
-        */
-
-       {
-        .name = "A1x",
-        .mt_mled = "MLED",
-        .mled_status = "\\MAIL",
-        .mt_lcd_switch = A1x_PREFIX "_Q10",
-        .lcd_status = "\\BKLI",
-        .brightness_up = A1x_PREFIX "_Q0E",
-        .brightness_down = A1x_PREFIX "_Q0F"},
-
-       {
-        .name = "A2x",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .wled_status = "\\SG66",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\BAOF",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "A4G",
-        .mt_mled = "MLED",
-/* WLED present, but not controlled by ACPI */
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\ADVG"},
-
-       {
-        .name = "D1x",
-        .mt_mled = "MLED",
-        .mt_lcd_switch = "\\Q0D",
-        .lcd_status = "\\GP11",
-        .brightness_up = "\\Q0C",
-        .brightness_down = "\\Q0B",
-        .brightness_status = "\\BLVL",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L2D",
-        .mt_mled = "MLED",
-        .mled_status = "\\SGP6",
-        .mt_wled = "WLED",
-        .wled_status = "\\RCP3",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\SGP0",
-        .brightness_up = "\\Q0E",
-        .brightness_down = "\\Q0F",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L3C",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = L3C_PREFIX "_Q10",
-        .lcd_status = "\\GL32",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"},
-
-       {
-        .name = "L3D",
-        .mt_mled = "MLED",
-        .mled_status = "\\MALD",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\BKLG",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L3H",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = "EHK",
-        .lcd_status = "\\_SB.PCI0.PM.PBC",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L4R",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .wled_status = "\\_SB.PCI0.SBRG.SG13",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
-
-       {
-        .name = "L5x",
-        .mt_mled = "MLED",
-/* WLED present, but not controlled by ACPI */
-        .mt_tled = "TLED",
-        .mt_lcd_switch = "\\Q0D",
-        .lcd_status = "\\BAOF",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L8L"
-/* No features, but at least support the hotkeys */
-        },
-
-       {
-        .name = "M1A",
-        .mt_mled = "MLED",
-        .mt_lcd_switch = M1A_PREFIX "Q10",
-        .lcd_status = "\\PNOF",
-        .brightness_up = M1A_PREFIX "Q0E",
-        .brightness_down = M1A_PREFIX "Q0F",
-        .brightness_status = "\\BRIT",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "M2E",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\GP06",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "M6N",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .wled_status = "\\_SB.PCI0.SBRG.SG13",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\_SB.BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\SSTE"},
-
-       {
-        .name = "M6R",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
-
-       {
-        .name = "P30",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = P30_PREFIX "_Q0E",
-        .lcd_status = "\\BKLT",
-        .brightness_up = P30_PREFIX "_Q68",
-        .brightness_down = P30_PREFIX "_Q69",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\DNXT"},
-
-       {
-        .name = "S1x",
-        .mt_mled = "MLED",
-        .mled_status = "\\EMLE",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = S1x_PREFIX "Q10",
-        .lcd_status = "\\PNOF",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV"},
-
-       {
-        .name = "S2x",
-        .mt_mled = "MLED",
-        .mled_status = "\\MAIL",
-        .mt_lcd_switch = S2x_PREFIX "_Q10",
-        .lcd_status = "\\BKLI",
-        .brightness_up = S2x_PREFIX "_Q0B",
-        .brightness_down = S2x_PREFIX "_Q0A"},
-
-       {
-        .name = "W1N",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_ledd = "SLCM",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\ADVG"},
-
-       {
-        .name = "W5A",
-        .mt_bt_switch = "BLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\ADVG"},
-
-       {
-        .name = "W3V",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "xxN",
-        .mt_mled = "MLED",
-/* WLED present, but not controlled by ACPI */
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-       .display_get = "\\ADVG"},
-
-       {
-               .name              = "A4S",
-               .brightness_set    = "SPLV",
-               .brightness_get    = "GPLV",
-               .mt_bt_switch      = "BLED",
-               .mt_wled           = "WLED"
-       },
-
-       {
-               .name           = "F3Sa",
-               .mt_bt_switch   = "BLED",
-               .mt_wled        = "WLED",
-               .mt_mled        = "MLED",
-               .brightness_get = "GPLV",
-               .brightness_set = "SPLV",
-               .mt_lcd_switch  = "\\_SB.PCI0.SBRG.EC0._Q10",
-               .lcd_status     = "\\_SB.PCI0.SBRG.EC0.RPIN",
-               .display_get    = "\\ADVG",
-               .display_set    = "SDSP",
-       },
-       {
-               .name = "R1F",
-               .mt_bt_switch = "BLED",
-               .mt_mled = "MLED",
-               .mt_wled = "WLED",
-               .mt_lcd_switch = "\\Q10",
-               .lcd_status = "\\GP06",
-               .brightness_set = "SPLV",
-               .brightness_get = "GPLV",
-               .display_set = "SDSP",
-               .display_get = "\\INFB"
-       }
-};
-
-/* procdir we use */
-static struct proc_dir_entry *asus_proc_dir;
-
-static struct backlight_device *asus_backlight_device;
-
-/*
- * This header is made available to allow proper configuration given model,
- * revision number , ... this info cannot go in struct asus_hotk because it is
- * available before the hotk
- */
-static struct acpi_table_header *asus_info;
-
-/* The actual device the driver binds to */
-static struct asus_hotk *hotk;
-
-/*
- * The hotkey driver and autoloading declaration
- */
-static int asus_hotk_add(struct acpi_device *device);
-static int asus_hotk_remove(struct acpi_device *device, int type);
-static void asus_hotk_notify(struct acpi_device *device, u32 event);
-
-static const struct acpi_device_id asus_device_ids[] = {
-       {"ATK0100", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, asus_device_ids);
-
-static struct acpi_driver asus_hotk_driver = {
-       .name = "asus_acpi",
-       .class = ACPI_HOTK_CLASS,
-       .owner = THIS_MODULE,
-       .ids = asus_device_ids,
-       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-       .ops = {
-               .add = asus_hotk_add,
-               .remove = asus_hotk_remove,
-               .notify = asus_hotk_notify,
-               },
-};
-
-/*
- * This function evaluates an ACPI method, given an int as parameter, the
- * method is searched within the scope of the handle, can be NULL. The output
- * of the method is written is output, which can also be NULL
- *
- * returns 1 if write is successful, 0 else.
- */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
-                         struct acpi_buffer *output)
-{
-       struct acpi_object_list params; /* list of input parameters (int) */
-       union acpi_object in_obj;       /* the only param we use */
-       acpi_status status;
-
-       params.count = 1;
-       params.pointer = &in_obj;
-       in_obj.type = ACPI_TYPE_INTEGER;
-       in_obj.integer.value = val;
-
-       status = acpi_evaluate_object(handle, (char *)method, &params, output);
-       return (status == AE_OK);
-}
-
-static int read_acpi_int(acpi_handle handle, const char *method, int *val)
-{
-       struct acpi_buffer output;
-       union acpi_object out_obj;
-       acpi_status status;
-
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
-       *val = out_obj.integer.value;
-       return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
-}
-
-static int asus_info_proc_show(struct seq_file *m, void *v)
-{
-       int temp;
-
-       seq_printf(m, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
-       seq_printf(m, "Model reference    : %s\n", hotk->methods->name);
-       /*
-        * The SFUN method probably allows the original driver to get the list
-        * of features supported by a given model. For now, 0x0100 or 0x0800
-        * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
-        * The significance of others is yet to be found.
-        */
-       if (read_acpi_int(hotk->handle, "SFUN", &temp))
-               seq_printf(m, "SFUN value         : 0x%04x\n", temp);
-       /*
-        * Another value for userspace: the ASYM method returns 0x02 for
-        * battery low and 0x04 for battery critical, its readings tend to be
-        * more accurate than those provided by _BST.
-        * Note: since not all the laptops provide this method, errors are
-        * silently ignored.
-        */
-       if (read_acpi_int(hotk->handle, "ASYM", &temp))
-               seq_printf(m, "ASYM value         : 0x%04x\n", temp);
-       if (asus_info) {
-               seq_printf(m, "DSDT length        : %d\n", asus_info->length);
-               seq_printf(m, "DSDT checksum      : %d\n", asus_info->checksum);
-               seq_printf(m, "DSDT revision      : %d\n", asus_info->revision);
-               seq_printf(m, "OEM id             : %.*s\n", ACPI_OEM_ID_SIZE, asus_info->oem_id);
-               seq_printf(m, "OEM table id       : %.*s\n", ACPI_OEM_TABLE_ID_SIZE, asus_info->oem_table_id);
-               seq_printf(m, "OEM revision       : 0x%x\n", asus_info->oem_revision);
-               seq_printf(m, "ASL comp vendor id : %.*s\n", ACPI_NAME_SIZE, asus_info->asl_compiler_id);
-               seq_printf(m, "ASL comp revision  : 0x%x\n", asus_info->asl_compiler_revision);
-       }
-
-       return 0;
-}
-
-static int asus_info_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, asus_info_proc_show, NULL);
-}
-
-static const struct file_operations asus_info_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = asus_info_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-/*
- * /proc handlers
- * We write our info in page, we begin at offset off and cannot write more
- * than count bytes. We set eof to 1 if we handle those 2 values. We return the
- * number of bytes written in page
- */
-
-/* Generic LED functions */
-static int read_led(const char *ledname, int ledmask)
-{
-       if (ledname) {
-               int led_status;
-
-               if (read_acpi_int(NULL, ledname, &led_status))
-                       return led_status;
-               else
-                       pr_warn("Error reading LED status\n");
-       }
-       return (hotk->status & ledmask) ? 1 : 0;
-}
-
-static int parse_arg(const char __user *buf, unsigned long count, int *val)
-{
-       char s[32];
-       if (!count)
-               return 0;
-       if (count > 31)
-               return -EINVAL;
-       if (copy_from_user(s, buf, count))
-               return -EFAULT;
-       s[count] = 0;
-       if (sscanf(s, "%i", val) != 1)
-               return -EINVAL;
-       return count;
-}
-
-/* FIXME: kill extraneous args so it can be called independently */
-static int
-write_led(const char __user *buffer, unsigned long count,
-         char *ledname, int ledmask, int invert)
-{
-       int rv, value;
-       int led_out = 0;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0)
-               led_out = value ? 1 : 0;
-
-       hotk->status =
-           (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
-
-       if (invert)             /* invert target value */
-               led_out = !led_out;
-
-       if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
-               pr_warn("LED (%s) write failed\n", ledname);
-
-       return rv;
-}
-
-/*
- * Proc handlers for MLED
- */
-static int mled_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
-       return 0;
-}
-
-static int mled_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, mled_proc_show, NULL);
-}
-
-static ssize_t mled_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
-}
-
-static const struct file_operations mled_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = mled_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = mled_proc_write,
-};
-
-/*
- * Proc handlers for LED display
- */
-static int ledd_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "0x%08x\n", hotk->ledd_status);
-       return 0;
-}
-
-static int ledd_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ledd_proc_show, NULL);
-}
-
-static ssize_t ledd_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0) {
-               if (!write_acpi_int
-                   (hotk->handle, hotk->methods->mt_ledd, value, NULL))
-                       pr_warn("LED display write failed\n");
-               else
-                       hotk->ledd_status = (u32) value;
-       }
-       return rv;
-}
-
-static const struct file_operations ledd_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = ledd_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = ledd_proc_write,
-};
-
-/*
- * Proc handlers for WLED
- */
-static int wled_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
-       return 0;
-}
-
-static int wled_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, wled_proc_show, NULL);
-}
-
-static ssize_t wled_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
-}
-
-static const struct file_operations wled_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = wled_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = wled_proc_write,
-};
-
-/*
- * Proc handlers for Bluetooth
- */
-static int bluetooth_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->bt_status, BT_ON));
-       return 0;
-}
-
-static int bluetooth_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, bluetooth_proc_show, NULL);
-}
-
-static ssize_t bluetooth_proc_write(struct file *file,
-               const char __user *buffer, size_t count, loff_t *pos)
-{
-       /* Note: mt_bt_switch controls both internal Bluetooth adapter's
-          presence and its LED */
-       return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0);
-}
-
-static const struct file_operations bluetooth_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = bluetooth_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = bluetooth_proc_write,
-};
-
-/*
- * Proc handlers for TLED
- */
-static int tled_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
-       return 0;
-}
-
-static int tled_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, tled_proc_show, NULL);
-}
-
-static ssize_t tled_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
-}
-
-static const struct file_operations tled_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = tled_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = tled_proc_write,
-};
-
-static int get_lcd_state(void)
-{
-       int lcd = 0;
-
-       if (hotk->model == L3H) {
-               /* L3H and the like have to be handled differently */
-               acpi_status status = 0;
-               struct acpi_object_list input;
-               union acpi_object mt_params[2];
-               struct acpi_buffer output;
-               union acpi_object out_obj;
-
-               input.count = 2;
-               input.pointer = mt_params;
-               /* Note: the following values are partly guessed up, but
-                  otherwise they seem to work */
-               mt_params[0].type = ACPI_TYPE_INTEGER;
-               mt_params[0].integer.value = 0x02;
-               mt_params[1].type = ACPI_TYPE_INTEGER;
-               mt_params[1].integer.value = 0x02;
-
-               output.length = sizeof(out_obj);
-               output.pointer = &out_obj;
-
-               status =
-                   acpi_evaluate_object(NULL, hotk->methods->lcd_status,
-                                        &input, &output);
-               if (status != AE_OK)
-                       return -1;
-               if (out_obj.type == ACPI_TYPE_INTEGER)
-                       /* That's what the AML code does */
-                       lcd = out_obj.integer.value >> 8;
-       } else if (hotk->model == F3Sa) {
-               unsigned long long tmp;
-               union acpi_object param;
-               struct acpi_object_list input;
-               acpi_status status;
-
-               /* Read pin 11 */
-               param.type = ACPI_TYPE_INTEGER;
-               param.integer.value = 0x11;
-               input.count = 1;
-               input.pointer = &param;
-
-               status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status,
-                                               &input, &tmp);
-               if (status != AE_OK)
-                       return -1;
-
-               lcd = tmp;
-       } else {
-               /* We don't have to check anything if we are here */
-               if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
-                       pr_warn("Error reading LCD status\n");
-
-               if (hotk->model == L2D)
-                       lcd = ~lcd;
-       }
-
-       return (lcd & 1);
-}
-
-static int set_lcd_state(int value)
-{
-       int lcd = 0;
-       acpi_status status = 0;
-
-       lcd = value ? 1 : 0;
-       if (lcd != get_lcd_state()) {
-               /* switch */
-               if (hotk->model != L3H) {
-                       status =
-                           acpi_evaluate_object(NULL,
-                                                hotk->methods->mt_lcd_switch,
-                                                NULL, NULL);
-               } else {
-                       /* L3H and the like must be handled differently */
-                       if (!write_acpi_int
-                           (hotk->handle, hotk->methods->mt_lcd_switch, 0x07,
-                            NULL))
-                               status = AE_ERROR;
-                       /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
-                          the exact behaviour is simulated here */
-               }
-               if (ACPI_FAILURE(status))
-                       pr_warn("Error switching LCD\n");
-       }
-       return 0;
-
-}
-
-static int lcd_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", get_lcd_state());
-       return 0;
-}
-
-static int lcd_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, lcd_proc_show, NULL);
-}
-
-static ssize_t lcd_proc_write(struct file *file, const char __user *buffer,
-              size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0)
-               set_lcd_state(value);
-       return rv;
-}
-
-static const struct file_operations lcd_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = lcd_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = lcd_proc_write,
-};
-
-static int read_brightness(struct backlight_device *bd)
-{
-       int value;
-
-       if (hotk->methods->brightness_get) {    /* SPLV/GPLV laptop */
-               if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
-                                  &value))
-                       pr_warn("Error reading brightness\n");
-       } else if (hotk->methods->brightness_status) {  /* For D1 for example */
-               if (!read_acpi_int(NULL, hotk->methods->brightness_status,
-                                  &value))
-                       pr_warn("Error reading brightness\n");
-       } else                  /* No GPLV method */
-               value = hotk->brightness;
-       return value;
-}
-
-/*
- * Change the brightness level
- */
-static int set_brightness(int value)
-{
-       acpi_status status = 0;
-       int ret = 0;
-
-       /* SPLV laptop */
-       if (hotk->methods->brightness_set) {
-               if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
-                                   value, NULL)) {
-                       pr_warn("Error changing brightness\n");
-                       ret = -EIO;
-               }
-               goto out;
-       }
-
-       /* No SPLV method if we are here, act as appropriate */
-       value -= read_brightness(NULL);
-       while (value != 0) {
-               status = acpi_evaluate_object(NULL, (value > 0) ?
-                                             hotk->methods->brightness_up :
-                                             hotk->methods->brightness_down,
-                                             NULL, NULL);
-               (value > 0) ? value-- : value++;
-               if (ACPI_FAILURE(status)) {
-                       pr_warn("Error changing brightness\n");
-                       ret = -EIO;
-               }
-       }
-out:
-       return ret;
-}
-
-static int set_brightness_status(struct backlight_device *bd)
-{
-       return set_brightness(bd->props.brightness);
-}
-
-static int brn_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_brightness(NULL));
-       return 0;
-}
-
-static int brn_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, brn_proc_show, NULL);
-}
-
-static ssize_t brn_proc_write(struct file *file, const char __user *buffer,
-              size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0) {
-               value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
-               /* 0 <= value <= 15 */
-               set_brightness(value);
-       }
-       return rv;
-}
-
-static const struct file_operations brn_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = brn_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = brn_proc_write,
-};
-
-static void set_display(int value)
-{
-       /* no sanity check needed for now */
-       if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
-                           value, NULL))
-               pr_warn("Error setting display\n");
-       return;
-}
-
-/*
- * Now, *this* one could be more user-friendly, but so far, no-one has
- * complained. The significance of bits is the same as in proc_write_disp()
- */
-static int disp_proc_show(struct seq_file *m, void *v)
-{
-       int value = 0;
-
-       if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
-               pr_warn("Error reading display status\n");
-       value &= 0x07;  /* needed for some models, shouldn't hurt others */
-       seq_printf(m, "%d\n", value);
-       return 0;
-}
-
-static int disp_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, disp_proc_show, NULL);
-}
-
-/*
- * Experimental support for display switching. As of now: 1 should activate
- * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
- * (bitwise) of these will suffice. I never actually tested 3 displays hooked
- * up simultaneously, so be warned. See the acpi4asus README for more info.
- */
-static ssize_t disp_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0)
-               set_display(value);
-       return rv;
-}
-
-static const struct file_operations disp_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = disp_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = disp_proc_write,
-};
-
-static int
-asus_proc_add(char *name, const struct file_operations *proc_fops, umode_t mode,
-                    struct acpi_device *device)
-{
-       struct proc_dir_entry *proc;
-
-       proc = proc_create_data(name, mode, acpi_device_dir(device),
-                               proc_fops, acpi_driver_data(device));
-       if (!proc) {
-               pr_warn("  Unable to create %s fs entry\n", name);
-               return -1;
-       }
-       proc->uid = asus_uid;
-       proc->gid = asus_gid;
-       return 0;
-}
-
-static int asus_hotk_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *proc;
-       umode_t mode;
-
-       if ((asus_uid == 0) && (asus_gid == 0)) {
-               mode = S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP;
-       } else {
-               mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
-               pr_warn("  asus_uid and asus_gid parameters are "
-                       "deprecated, use chown and chmod instead!\n");
-       }
-
-       acpi_device_dir(device) = asus_proc_dir;
-       if (!acpi_device_dir(device))
-               return -ENODEV;
-
-       proc = proc_create(PROC_INFO, mode, acpi_device_dir(device),
-                          &asus_info_proc_fops);
-       if (proc) {
-               proc->uid = asus_uid;
-               proc->gid = asus_gid;
-       } else {
-               pr_warn("  Unable to create " PROC_INFO " fs entry\n");
-       }
-
-       if (hotk->methods->mt_wled) {
-               asus_proc_add(PROC_WLED, &wled_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_ledd) {
-               asus_proc_add(PROC_LEDD, &ledd_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_mled) {
-               asus_proc_add(PROC_MLED, &mled_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_tled) {
-               asus_proc_add(PROC_TLED, &tled_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_bt_switch) {
-               asus_proc_add(PROC_BT, &bluetooth_proc_fops, mode, device);
-       }
-
-       /*
-        * We need both read node and write method as LCD switch is also
-        * accessible from the keyboard
-        */
-       if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
-               asus_proc_add(PROC_LCD, &lcd_proc_fops, mode, device);
-       }
-
-       if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
-           (hotk->methods->brightness_get && hotk->methods->brightness_set)) {
-               asus_proc_add(PROC_BRN, &brn_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->display_set) {
-               asus_proc_add(PROC_DISP, &disp_proc_fops, mode, device);
-       }
-
-       return 0;
-}
-
-static int asus_hotk_remove_fs(struct acpi_device *device)
-{
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(PROC_INFO, acpi_device_dir(device));
-               if (hotk->methods->mt_wled)
-                       remove_proc_entry(PROC_WLED, acpi_device_dir(device));
-               if (hotk->methods->mt_mled)
-                       remove_proc_entry(PROC_MLED, acpi_device_dir(device));
-               if (hotk->methods->mt_tled)
-                       remove_proc_entry(PROC_TLED, acpi_device_dir(device));
-               if (hotk->methods->mt_ledd)
-                       remove_proc_entry(PROC_LEDD, acpi_device_dir(device));
-               if (hotk->methods->mt_bt_switch)
-                       remove_proc_entry(PROC_BT, acpi_device_dir(device));
-               if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
-                       remove_proc_entry(PROC_LCD, acpi_device_dir(device));
-               if ((hotk->methods->brightness_up
-                    && hotk->methods->brightness_down)
-                   || (hotk->methods->brightness_get
-                       && hotk->methods->brightness_set))
-                       remove_proc_entry(PROC_BRN, acpi_device_dir(device));
-               if (hotk->methods->display_set)
-                       remove_proc_entry(PROC_DISP, acpi_device_dir(device));
-       }
-       return 0;
-}
-
-static void asus_hotk_notify(struct acpi_device *device, u32 event)
-{
-       /* TODO Find a better way to handle events count. */
-       if (!hotk)
-               return;
-
-       /*
-        * The BIOS *should* be sending us device events, but apparently
-        * Asus uses system events instead, so just ignore any device
-        * events we get.
-        */
-       if (event > ACPI_MAX_SYS_NOTIFY)
-               return;
-
-       if ((event & ~((u32) BR_UP)) < 16)
-               hotk->brightness = (event & ~((u32) BR_UP));
-       else if ((event & ~((u32) BR_DOWN)) < 16)
-               hotk->brightness = (event & ~((u32) BR_DOWN));
-
-       acpi_bus_generate_proc_event(hotk->device, event,
-                               hotk->event_count[event % 128]++);
-
-       return;
-}
-
-/*
- * Match the model string to the list of supported models. Return END_MODEL if
- * no match or model is NULL.
- */
-static int asus_model_match(char *model)
-{
-       if (model == NULL)
-               return END_MODEL;
-
-       if (strncmp(model, "L3D", 3) == 0)
-               return L3D;
-       else if (strncmp(model, "L2E", 3) == 0 ||
-                strncmp(model, "L3H", 3) == 0 || strncmp(model, "L5D", 3) == 0)
-               return L3H;
-       else if (strncmp(model, "L3", 2) == 0 || strncmp(model, "L2B", 3) == 0)
-               return L3C;
-       else if (strncmp(model, "L8L", 3) == 0)
-               return L8L;
-       else if (strncmp(model, "L4R", 3) == 0)
-               return L4R;
-       else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0)
-               return M6N;
-       else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0)
-               return M6R;
-       else if (strncmp(model, "M2N", 3) == 0 ||
-                strncmp(model, "M3N", 3) == 0 ||
-                strncmp(model, "M5N", 3) == 0 ||
-                strncmp(model, "S1N", 3) == 0 ||
-                strncmp(model, "S5N", 3) == 0)
-               return xxN;
-       else if (strncmp(model, "M1", 2) == 0)
-               return M1A;
-       else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0)
-               return M2E;
-       else if (strncmp(model, "L2", 2) == 0)
-               return L2D;
-       else if (strncmp(model, "L8", 2) == 0)
-               return S1x;
-       else if (strncmp(model, "D1", 2) == 0)
-               return D1x;
-       else if (strncmp(model, "A1", 2) == 0)
-               return A1x;
-       else if (strncmp(model, "A2", 2) == 0)
-               return A2x;
-       else if (strncmp(model, "J1", 2) == 0)
-               return S2x;
-       else if (strncmp(model, "L5", 2) == 0)
-               return L5x;
-       else if (strncmp(model, "A4G", 3) == 0)
-               return A4G;
-       else if (strncmp(model, "W1N", 3) == 0)
-               return W1N;
-       else if (strncmp(model, "W3V", 3) == 0)
-               return W3V;
-       else if (strncmp(model, "W5A", 3) == 0)
-               return W5A;
-       else if (strncmp(model, "R1F", 3) == 0)
-               return R1F;
-       else if (strncmp(model, "A4S", 3) == 0)
-               return A4S;
-       else if (strncmp(model, "F3Sa", 4) == 0)
-               return F3Sa;
-       else
-               return END_MODEL;
-}
-
-/*
- * This function is used to initialize the hotk with right values. In this
- * method, we can make all the detection we want, and modify the hotk struct
- */
-static int asus_hotk_get_info(void)
-{
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *model = NULL;
-       int bsts_result;
-       char *string = NULL;
-       acpi_status status;
-
-       /*
-        * Get DSDT headers early enough to allow for differentiating between
-        * models, but late enough to allow acpi_bus_register_driver() to fail
-        * before doing anything ACPI-specific. Should we encounter a machine,
-        * which needs special handling (i.e. its hotkey device has a different
-        * HID), this bit will be moved. A global variable asus_info contains
-        * the DSDT header.
-        */
-       status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
-       if (ACPI_FAILURE(status))
-               pr_warn("  Couldn't get the DSDT table header\n");
-
-       /* We have to write 0 on init this far for all ASUS models */
-       if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
-               pr_err("  Hotkey initialization failed\n");
-               return -ENODEV;
-       }
-
-       /* This needs to be called for some laptops to init properly */
-       if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
-               pr_warn("  Error calling BSTS\n");
-       else if (bsts_result)
-               pr_notice("  BSTS called, 0x%02x returned\n", bsts_result);
-
-       /*
-        * Try to match the object returned by INIT to the specific model.
-        * Handle every possible object (or the lack of thereof) the DSDT
-        * writers might throw at us. When in trouble, we pass NULL to
-        * asus_model_match() and try something completely different.
-        */
-       if (buffer.pointer) {
-               model = buffer.pointer;
-               switch (model->type) {
-               case ACPI_TYPE_STRING:
-                       string = model->string.pointer;
-                       break;
-               case ACPI_TYPE_BUFFER:
-                       string = model->buffer.pointer;
-                       break;
-               default:
-                       kfree(model);
-                       model = NULL;
-                       break;
-               }
-       }
-       hotk->model = asus_model_match(string);
-       if (hotk->model == END_MODEL) { /* match failed */
-               if (asus_info &&
-                   strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
-                       hotk->model = P30;
-                       pr_notice("  Samsung P30 detected, supported\n");
-                       hotk->methods = &model_conf[hotk->model];
-                       kfree(model);
-                       return 0;
-               } else {
-                       hotk->model = M2E;
-                       pr_notice("  unsupported model %s, trying default values\n",
-                                 string);
-                       pr_notice("  send /proc/acpi/dsdt to the developers\n");
-                       kfree(model);
-                       return -ENODEV;
-               }
-       }
-       hotk->methods = &model_conf[hotk->model];
-       pr_notice("  %s model detected, supported\n", string);
-
-       /* Sort of per-model blacklist */
-       if (strncmp(string, "L2B", 3) == 0)
-               hotk->methods->lcd_status = NULL;
-       /* L2B is similar enough to L3C to use its settings, with this only
-          exception */
-       else if (strncmp(string, "A3G", 3) == 0)
-               hotk->methods->lcd_status = "\\BLFG";
-       /* A3G is like M6R */
-       else if (strncmp(string, "S5N", 3) == 0 ||
-                strncmp(string, "M5N", 3) == 0 ||
-                strncmp(string, "W3N", 3) == 0)
-               hotk->methods->mt_mled = NULL;
-       /* S5N, M5N and W3N have no MLED */
-       else if (strncmp(string, "L5D", 3) == 0)
-               hotk->methods->mt_wled = NULL;
-       /* L5D's WLED is not controlled by ACPI */
-       else if (strncmp(string, "M2N", 3) == 0 ||
-                strncmp(string, "W3V", 3) == 0 ||
-                strncmp(string, "S1N", 3) == 0)
-               hotk->methods->mt_wled = "WLED";
-       /* M2N, S1N and W3V have a usable WLED */
-       else if (asus_info) {
-               if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
-                       hotk->methods->mled_status = NULL;
-               /* S1300A reports L84F, but L1400B too, account for that */
-       }
-
-       kfree(model);
-
-       return 0;
-}
-
-static int asus_hotk_check(void)
-{
-       int result = 0;
-
-       result = acpi_bus_get_status(hotk->device);
-       if (result)
-               return result;
-
-       if (hotk->device->status.present) {
-               result = asus_hotk_get_info();
-       } else {
-               pr_err("  Hotkey device not present, aborting\n");
-               return -EINVAL;
-       }
-
-       return result;
-}
-
-static int asus_hotk_found;
-
-static int asus_hotk_add(struct acpi_device *device)
-{
-       acpi_status status = AE_OK;
-       int result;
-
-       pr_notice("Asus Laptop ACPI Extras version %s\n", ASUS_ACPI_VERSION);
-
-       hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
-       if (!hotk)
-               return -ENOMEM;
-
-       hotk->handle = device->handle;
-       strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
-       device->driver_data = hotk;
-       hotk->device = device;
-
-       result = asus_hotk_check();
-       if (result)
-               goto end;
-
-       result = asus_hotk_add_fs(device);
-       if (result)
-               goto end;
-
-       /* For laptops without GPLV: init the hotk->brightness value */
-       if ((!hotk->methods->brightness_get)
-           && (!hotk->methods->brightness_status)
-           && (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
-               status =
-                   acpi_evaluate_object(NULL, hotk->methods->brightness_down,
-                                        NULL, NULL);
-               if (ACPI_FAILURE(status))
-                       pr_warn("  Error changing brightness\n");
-               else {
-                       status =
-                           acpi_evaluate_object(NULL,
-                                                hotk->methods->brightness_up,
-                                                NULL, NULL);
-                       if (ACPI_FAILURE(status))
-                               pr_warn("  Strange, error changing brightness\n");
-               }
-       }
-
-       asus_hotk_found = 1;
-
-       /* LED display is off by default */
-       hotk->ledd_status = 0xFFF;
-
-end:
-       if (result)
-               kfree(hotk);
-
-       return result;
-}
-
-static int asus_hotk_remove(struct acpi_device *device, int type)
-{
-       asus_hotk_remove_fs(device);
-
-       kfree(hotk);
-
-       return 0;
-}
-
-static const struct backlight_ops asus_backlight_data = {
-       .get_brightness = read_brightness,
-       .update_status  = set_brightness_status,
-};
-
-static void asus_acpi_exit(void)
-{
-       if (asus_backlight_device)
-               backlight_device_unregister(asus_backlight_device);
-
-       acpi_bus_unregister_driver(&asus_hotk_driver);
-       remove_proc_entry(PROC_ASUS, acpi_root_dir);
-
-       return;
-}
-
-static int __init asus_acpi_init(void)
-{
-       struct backlight_properties props;
-       int result;
-
-       result = acpi_bus_register_driver(&asus_hotk_driver);
-       if (result < 0)
-               return result;
-
-       asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
-       if (!asus_proc_dir) {
-               pr_err("Unable to create /proc entry\n");
-               acpi_bus_unregister_driver(&asus_hotk_driver);
-               return -ENODEV;
-       }
-
-       /*
-        * This is a bit of a kludge.  We only want this module loaded
-        * for ASUS systems, but there's currently no way to probe the
-        * ACPI namespace for ASUS HIDs.  So we just return failure if
-        * we didn't find one, which will cause the module to be
-        * unloaded.
-        */
-       if (!asus_hotk_found) {
-               acpi_bus_unregister_driver(&asus_hotk_driver);
-               remove_proc_entry(PROC_ASUS, acpi_root_dir);
-               return -ENODEV;
-       }
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_PLATFORM;
-       props.max_brightness = 15;
-       asus_backlight_device = backlight_device_register("asus", NULL, NULL,
-                                                         &asus_backlight_data,
-                                                         &props);
-       if (IS_ERR(asus_backlight_device)) {
-               pr_err("Could not register asus backlight device\n");
-               asus_backlight_device = NULL;
-               asus_acpi_exit();
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-module_init(asus_acpi_init);
-module_exit(asus_acpi_exit);
index d96734478324b77d28a314858fa1c889a70977b7..1887e2f166a43edeb449ae2851c8f77a8a63bcfc 100644 (file)
@@ -882,6 +882,7 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, compal_dmi_table);
 
 static void initialize_power_supply_data(struct compal_data *data)
 {
@@ -1097,16 +1098,3 @@ MODULE_AUTHOR("Roald Frederickx (roald.frederickx@gmail.com)");
 MODULE_DESCRIPTION("Compal Laptop Support");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("dmi:*:rnIFL90:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
-MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnJHL90:rvrREFERENCE:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1012:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*");
index d93e962f26100c7e0498f80f7dac437c6f0e87f5..a05fc9c955d86212cc274b8f78296c994342e2b0 100644 (file)
@@ -117,6 +117,7 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, dell_device_table);
 
 static struct dmi_system_id __devinitdata dell_blacklist[] = {
        /* Supported by compal-laptop */
@@ -184,6 +185,33 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {
                },
                .driver_data = &quirk_dell_vostro_v130,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell Vostro 3555",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"),
+               },
+               .driver_data = &quirk_dell_vostro_v130,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell Inspiron N311z",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"),
+               },
+               .driver_data = &quirk_dell_vostro_v130,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell Inspiron M5110",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
+               },
+               .driver_data = &quirk_dell_vostro_v130,
+       },
 };
 
 static struct calling_interface_buffer *buffer;
@@ -236,9 +264,7 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
 {
        switch (dm->type) {
        case 0xd4: /* Indexed IO */
-               break;
        case 0xd5: /* Protected Area Type 1 */
-               break;
        case 0xd6: /* Protected Area Type 2 */
                break;
        case 0xda: /* Calling interface */
@@ -615,6 +641,7 @@ static void touchpad_led_set(struct led_classdev *led_cdev,
 static struct led_classdev touchpad_led = {
        .name = "dell-laptop::touchpad",
        .brightness_set = touchpad_led_set,
+       .flags = LED_CORE_SUSPENDRESUME,
 };
 
 static int __devinit touchpad_led_init(struct device *dev)
@@ -794,6 +821,3 @@ module_exit(dell_exit);
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_DESCRIPTION("Dell laptop driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
-MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*");
-MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
index d9a9e2bedb30311f9423adc276c29d19c47503f5..dab91b48d22cf5fbb955efd7ecb5fc0f6fa318c1 100644 (file)
@@ -1251,6 +1251,14 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
 /*
  * ACPI driver
  */
+static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
+{
+       if (!eeepc->inputdev)
+               return ;
+       if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
+               pr_info("Unknown key %x pressed\n", event);
+}
+
 static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
 {
        struct eeepc_laptop *eeepc = acpi_driver_data(device);
@@ -1287,12 +1295,11 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
                                * event will be desired value (or else ignored)
                                */
                        }
-                       sparse_keymap_report_event(eeepc->inputdev, event,
-                                                  1, true);
+                       eeepc_input_notify(eeepc, event);
                }
        } else {
                /* Everything else is a bona-fide keypress event */
-               sparse_keymap_report_event(eeepc->inputdev, event, 1, true);
+               eeepc_input_notify(eeepc, event);
        }
 }
 
index 9f6e64302b457b04fb0871524e9ac906af34399f..656761380342006d8b13ad344610b8e70f9822d2 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
 #include <linux/dmi.h>
+#include <linux/fb.h>
 #include <acpi/acpi_bus.h>
 
 #include "asus-wmi.h"
@@ -84,9 +85,81 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
        { KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
        { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
+       { KE_KEY, 0xf3, { KEY_MENU } },
+       { KE_KEY, 0xf5, { KEY_HOMEPAGE } },
+       { KE_KEY, 0xf6, { KEY_ESC } },
        { KE_END, 0},
 };
 
+static struct quirk_entry quirk_asus_unknown = {
+};
+
+static struct quirk_entry quirk_asus_1000h = {
+       .hotplug_wireless = true,
+};
+
+static struct quirk_entry quirk_asus_et2012_type1 = {
+       .store_backlight_power = true,
+};
+
+static struct quirk_entry quirk_asus_et2012_type3 = {
+       .scalar_panel_brightness = true,
+       .store_backlight_power = true,
+};
+
+static struct quirk_entry *quirks;
+
+static void et2012_quirks(void)
+{
+       const struct dmi_device *dev = NULL;
+       char oemstring[30];
+
+       while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
+               if (sscanf(dev->name, "AEMS%24c", oemstring) == 1) {
+                       if (oemstring[18] == '1')
+                               quirks = &quirk_asus_et2012_type1;
+                       else if (oemstring[18] == '3')
+                               quirks = &quirk_asus_et2012_type3;
+                       break;
+               }
+       }
+}
+
+static int dmi_matched(const struct dmi_system_id *dmi)
+{
+       char *model;
+
+       quirks = dmi->driver_data;
+
+       model = (char *)dmi->matches[1].substr;
+       if (unlikely(strncmp(model, "ET2012", 6) == 0))
+               et2012_quirks();
+
+       return 1;
+}
+
+static struct dmi_system_id asus_quirks[] = {
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK Computer INC. 1000H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "1000H"),
+               },
+               .driver_data = &quirk_asus_1000h,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK Computer INC. ET2012E/I",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ET2012"),
+               },
+               .driver_data = &quirk_asus_unknown,
+       },
+       {},
+};
+
 static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
                                 unsigned int *value, bool *autorelease)
 {
@@ -141,33 +214,16 @@ static int eeepc_wmi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static void eeepc_dmi_check(struct asus_wmi_driver *driver)
-{
-       const char *model;
-
-       model = dmi_get_system_info(DMI_PRODUCT_NAME);
-       if (!model)
-               return;
-
-       /*
-        * Whitelist for wlan hotplug
-        *
-        * Asus 1000H needs the current hotplug code to handle
-        * Fn+F2 correctly. We may add other Asus here later, but
-        * it seems that most of the laptops supported by asus-wmi
-        * don't need to be on this list
-        */
-       if (strcmp(model, "1000H") == 0) {
-               driver->hotplug_wireless = true;
-               pr_info("wlan hotplug enabled\n");
-       }
-}
-
 static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
 {
-       driver->hotplug_wireless = hotplug_wireless;
-       driver->wapf = -1;
-       eeepc_dmi_check(driver);
+       quirks = &quirk_asus_unknown;
+       quirks->hotplug_wireless = hotplug_wireless;
+
+       dmi_check_system(asus_quirks);
+
+       driver->quirks = quirks;
+       driver->quirks->wapf = -1;
+       driver->panel_power = FB_BLANK_UNBLANK;
 }
 
 static struct asus_wmi_driver asus_wmi_driver = {
@@ -179,7 +235,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
        .input_phys = EEEPC_WMI_FILE "/input0",
        .key_filter = eeepc_wmi_key_filter,
        .probe = eeepc_wmi_probe,
-       .quirks = eeepc_wmi_quirks,
+       .detect_quirks = eeepc_wmi_quirks,
 };
 
 
index ba68d4e7a779cbec42c15f6d8bfa08b85ff8e2b0..7387f97a294194b607115096510f2119d76902d0 100644 (file)
@@ -375,7 +375,7 @@ static ssize_t hdaps_variance_show(struct device *dev,
 static ssize_t hdaps_temp1_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       u8 temp;
+       u8 uninitialized_var(temp);
        int ret;
 
        ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
@@ -388,7 +388,7 @@ static ssize_t hdaps_temp1_show(struct device *dev,
 static ssize_t hdaps_temp2_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       u8 temp;
+       u8 uninitialized_var(temp);
        int ret;
 
        ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
index 0903a883e9f4a92cd630ae071b854497a4be7092..0a3594c7e91263fcf7d1498e4e3634d4d8690ac2 100644 (file)
@@ -142,17 +142,7 @@ static struct platform_driver mfld_pb_driver = {
        .remove = __devexit_p(mfld_pb_remove),
 };
 
-static int __init mfld_pb_init(void)
-{
-       return platform_driver_register(&mfld_pb_driver);
-}
-module_init(mfld_pb_init);
-
-static void __exit mfld_pb_exit(void)
-{
-       platform_driver_unregister(&mfld_pb_driver);
-}
-module_exit(mfld_pb_exit);
+module_platform_driver(mfld_pb_driver);
 
 MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
 MODULE_DESCRIPTION("Intel Medfield Power Button Driver");
index 2ee9766737ea413d56e82d581444c64f1b696801..5ae9cd9c7e6e10f4da2dc254725f397286598731 100644 (file)
@@ -549,6 +549,7 @@ static int mid_thermal_remove(struct platform_device *pdev)
 
 static const struct platform_device_id therm_id_table[] = {
        { DRIVER_NAME, 1 },
+       { "msic_thermal", 1 },
        { }
 };
 
@@ -564,18 +565,7 @@ static struct platform_driver mid_thermal_driver = {
        .id_table = therm_id_table,
 };
 
-static int __init mid_thermal_module_init(void)
-{
-       return platform_driver_register(&mid_thermal_driver);
-}
-
-static void __exit mid_thermal_module_exit(void)
-{
-       platform_driver_unregister(&mid_thermal_driver);
-}
-
-module_init(mid_thermal_module_init);
-module_exit(mid_thermal_module_exit);
+module_platform_driver(mid_thermal_driver);
 
 MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
 MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
index 6ee0b5c909330849836c7c22dfd6713da62e25ab..79a0c2f6be53996c2771ffd532e517a6ac8bef4e 100644 (file)
@@ -313,6 +313,7 @@ static struct dmi_system_id __initdata oaktrail_dmi_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, oaktrail_dmi_table);
 
 static int __init oaktrail_init(void)
 {
@@ -394,4 +395,3 @@ MODULE_AUTHOR("Yin Kangkai (kangkai.yin@intel.com)");
 MODULE_DESCRIPTION("Intel Oaktrail Platform ACPI Extras");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("dmi:*:svnIntelCorporation:pnOakTrailplatform:*");
index fd73ea89b857872df7526c5c756872b3b9402f64..e2a34b42ddc1d584b5333fe9921d0d2c2b12dda4 100644 (file)
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/backlight.h>
+#include <linux/leds.h>
 #include <linux/fb.h>
 #include <linux/dmi.h>
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
+#include <linux/acpi.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/ctype.h>
+#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
+#include <acpi/video.h>
+#endif
 
 /*
  * This driver is needed because a number of Samsung laptops do not hook
 #define SABI_IFACE_COMPLETE            0x04
 #define SABI_IFACE_DATA                        0x05
 
-/* Structure to get data back to the calling function */
-struct sabi_retval {
-       u8 retval[20];
+#define WL_STATUS_WLAN                 0x0
+#define WL_STATUS_BT                   0x2
+
+/* Structure get/set data using sabi */
+struct sabi_data {
+       union {
+               struct {
+                       u32 d0;
+                       u32 d1;
+                       u16 d2;
+                       u8  d3;
+               };
+               u8 data[11];
+       };
 };
 
 struct sabi_header_offsets {
@@ -60,8 +79,8 @@ struct sabi_commands {
         * Brightness is 0 - 8, as described above.
         * Value 0 is for the BIOS to use
         */
-       u8 get_brightness;
-       u8 set_brightness;
+       u16 get_brightness;
+       u16 set_brightness;
 
        /*
         * first byte:
@@ -72,40 +91,56 @@ struct sabi_commands {
         * 0x03 - 3G is on
         * TODO, verify 3G is correct, that doesn't seem right...
         */
-       u8 get_wireless_button;
-       u8 set_wireless_button;
+       u16 get_wireless_button;
+       u16 set_wireless_button;
 
        /* 0 is off, 1 is on */
-       u8 get_backlight;
-       u8 set_backlight;
+       u16 get_backlight;
+       u16 set_backlight;
 
        /*
         * 0x80 or 0x00 - no action
         * 0x81 - recovery key pressed
         */
-       u8 get_recovery_mode;
-       u8 set_recovery_mode;
+       u16 get_recovery_mode;
+       u16 set_recovery_mode;
 
        /*
         * on seclinux: 0 is low, 1 is high,
         * on swsmi: 0 is normal, 1 is silent, 2 is turbo
         */
-       u8 get_performance_level;
-       u8 set_performance_level;
+       u16 get_performance_level;
+       u16 set_performance_level;
+
+       /* 0x80 is off, 0x81 is on */
+       u16 get_battery_life_extender;
+       u16 set_battery_life_extender;
+
+       /* 0x80 is off, 0x81 is on */
+       u16 get_usb_charge;
+       u16 set_usb_charge;
+
+       /* the first byte is for bluetooth and the third one is for wlan */
+       u16 get_wireless_status;
+       u16 set_wireless_status;
+
+       /* 0x81 to read, (0x82 | level << 8) to set, 0xaabb to enable */
+       u16 kbd_backlight;
 
        /*
         * Tell the BIOS that Linux is running on this machine.
         * 81 is on, 80 is off
         */
-       u8 set_linux;
+       u16 set_linux;
 };
 
 struct sabi_performance_level {
        const char *name;
-       u8 value;
+       u16 value;
 };
 
 struct sabi_config {
+       int sabi_version;
        const char *test_string;
        u16 main_function;
        const struct sabi_header_offsets header_offsets;
@@ -117,6 +152,10 @@ struct sabi_config {
 
 static const struct sabi_config sabi_configs[] = {
        {
+               /* I don't know if it is really 2, but it it is
+                * less than 3 anyway */
+               .sabi_version = 2,
+
                .test_string = "SECLINUX",
 
                .main_function = 0x4c49,
@@ -146,6 +185,17 @@ static const struct sabi_config sabi_configs[] = {
                        .get_performance_level = 0x08,
                        .set_performance_level = 0x09,
 
+                       .get_battery_life_extender = 0xFFFF,
+                       .set_battery_life_extender = 0xFFFF,
+
+                       .get_usb_charge = 0xFFFF,
+                       .set_usb_charge = 0xFFFF,
+
+                       .get_wireless_status = 0xFFFF,
+                       .set_wireless_status = 0xFFFF,
+
+                       .kbd_backlight = 0xFFFF,
+
                        .set_linux = 0x0a,
                },
 
@@ -164,6 +214,8 @@ static const struct sabi_config sabi_configs[] = {
                .max_brightness = 8,
        },
        {
+               .sabi_version = 3,
+
                .test_string = "SwSmi@",
 
                .main_function = 0x5843,
@@ -193,6 +245,17 @@ static const struct sabi_config sabi_configs[] = {
                        .get_performance_level = 0x31,
                        .set_performance_level = 0x32,
 
+                       .get_battery_life_extender = 0x65,
+                       .set_battery_life_extender = 0x66,
+
+                       .get_usb_charge = 0x67,
+                       .set_usb_charge = 0x68,
+
+                       .get_wireless_status = 0x69,
+                       .set_wireless_status = 0x6a,
+
+                       .kbd_backlight = 0x78,
+
                        .set_linux = 0xff,
                },
 
@@ -217,16 +280,82 @@ static const struct sabi_config sabi_configs[] = {
        { },
 };
 
-static const struct sabi_config *sabi_config;
+/*
+ * samsung-laptop/    - debugfs root directory
+ *   f0000_segment    - dump f0000 segment
+ *   command          - current command
+ *   data             - current data
+ *   d0, d1, d2, d3   - data fields
+ *   call             - call SABI using command and data
+ *
+ * This allow to call arbitrary sabi commands wihout
+ * modifying the driver at all.
+ * For example, setting the keyboard backlight brightness to 5
+ *
+ *  echo 0x78 > command
+ *  echo 0x0582 > d0
+ *  echo 0 > d1
+ *  echo 0 > d2
+ *  echo 0 > d3
+ *  cat call
+ */
+
+struct samsung_laptop_debug {
+       struct dentry *root;
+       struct sabi_data data;
+       u16 command;
+
+       struct debugfs_blob_wrapper f0000_wrapper;
+       struct debugfs_blob_wrapper data_wrapper;
+       struct debugfs_blob_wrapper sdiag_wrapper;
+};
+
+struct samsung_laptop;
+
+struct samsung_rfkill {
+       struct samsung_laptop *samsung;
+       struct rfkill *rfkill;
+       enum rfkill_type type;
+};
+
+struct samsung_laptop {
+       const struct sabi_config *config;
+
+       void __iomem *sabi;
+       void __iomem *sabi_iface;
+       void __iomem *f0000_segment;
+
+       struct mutex sabi_mutex;
+
+       struct platform_device *platform_device;
+       struct backlight_device *backlight_device;
+
+       struct samsung_rfkill wlan;
+       struct samsung_rfkill bluetooth;
+
+       struct led_classdev kbd_led;
+       int kbd_led_wk;
+       struct workqueue_struct *led_workqueue;
+       struct work_struct kbd_led_work;
+
+       struct samsung_laptop_debug debug;
+       struct samsung_quirks *quirks;
+
+       bool handle_backlight;
+       bool has_stepping_quirk;
+
+       char sdiag[64];
+};
+
+struct samsung_quirks {
+       bool broken_acpi_video;
+};
+
+static struct samsung_quirks samsung_unknown = {};
 
-static void __iomem *sabi;
-static void __iomem *sabi_iface;
-static void __iomem *f0000_segment;
-static struct backlight_device *backlight_device;
-static struct mutex sabi_mutex;
-static struct platform_device *sdev;
-static struct rfkill *rfk;
-static bool has_stepping_quirk;
+static struct samsung_quirks samsung_broken_acpi_video = {
+       .broken_acpi_video = true,
+};
 
 static bool force;
 module_param(force, bool, 0);
@@ -237,176 +366,143 @@ static bool debug;
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
-static int sabi_get_command(u8 command, struct sabi_retval *sretval)
+static int sabi_command(struct samsung_laptop *samsung, u16 command,
+                       struct sabi_data *in,
+                       struct sabi_data *out)
 {
-       int retval = 0;
-       u16 port = readw(sabi + sabi_config->header_offsets.port);
+       const struct sabi_config *config = samsung->config;
+       int ret = 0;
+       u16 port = readw(samsung->sabi + config->header_offsets.port);
        u8 complete, iface_data;
 
-       mutex_lock(&sabi_mutex);
-
-       /* enable memory to be able to write to it */
-       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
-
-       /* write out the command */
-       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
-       writew(command, sabi_iface + SABI_IFACE_SUB);
-       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
-
-       /* write protect memory to make it safe */
-       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+       mutex_lock(&samsung->sabi_mutex);
 
-       /* see if the command actually succeeded */
-       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
-       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
-       if (complete != 0xaa || iface_data == 0xff) {
-               pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
-                       command, complete, iface_data);
-               retval = -EINVAL;
-               goto exit;
+       if (debug) {
+               if (in)
+                       pr_info("SABI command:0x%04x "
+                               "data:{0x%08x, 0x%08x, 0x%04x, 0x%02x}",
+                               command, in->d0, in->d1, in->d2, in->d3);
+               else
+                       pr_info("SABI command:0x%04x", command);
        }
-       /*
-        * Save off the data into a structure so the caller use it.
-        * Right now we only want the first 4 bytes,
-        * There are commands that need more, but not for the ones we
-        * currently care about.
-        */
-       sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
-       sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
-       sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
-       sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
-
-exit:
-       mutex_unlock(&sabi_mutex);
-       return retval;
-
-}
-
-static int sabi_set_command(u8 command, u8 data)
-{
-       int retval = 0;
-       u16 port = readw(sabi + sabi_config->header_offsets.port);
-       u8 complete, iface_data;
-
-       mutex_lock(&sabi_mutex);
 
        /* enable memory to be able to write to it */
-       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
+       outb(readb(samsung->sabi + config->header_offsets.en_mem), port);
 
        /* write out the command */
-       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
-       writew(command, sabi_iface + SABI_IFACE_SUB);
-       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-       writeb(data, sabi_iface + SABI_IFACE_DATA);
-       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
+       writew(config->main_function, samsung->sabi_iface + SABI_IFACE_MAIN);
+       writew(command, samsung->sabi_iface + SABI_IFACE_SUB);
+       writeb(0, samsung->sabi_iface + SABI_IFACE_COMPLETE);
+       if (in) {
+               writel(in->d0, samsung->sabi_iface + SABI_IFACE_DATA);
+               writel(in->d1, samsung->sabi_iface + SABI_IFACE_DATA + 4);
+               writew(in->d2, samsung->sabi_iface + SABI_IFACE_DATA + 8);
+               writeb(in->d3, samsung->sabi_iface + SABI_IFACE_DATA + 10);
+       }
+       outb(readb(samsung->sabi + config->header_offsets.iface_func), port);
 
        /* write protect memory to make it safe */
-       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+       outb(readb(samsung->sabi + config->header_offsets.re_mem), port);
 
        /* see if the command actually succeeded */
-       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
-       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+       complete = readb(samsung->sabi_iface + SABI_IFACE_COMPLETE);
+       iface_data = readb(samsung->sabi_iface + SABI_IFACE_DATA);
+
+       /* iface_data = 0xFF happens when a command is not known
+        * so we only add a warning in debug mode since we will
+        * probably issue some unknown command at startup to find
+        * out which features are supported */
+       if (complete != 0xaa || (iface_data == 0xff && debug))
+               pr_warn("SABI command 0x%04x failed with"
+                       " completion flag 0x%02x and interface data 0x%02x",
+                       command, complete, iface_data);
+
        if (complete != 0xaa || iface_data == 0xff) {
-               pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
-                      command, complete, iface_data);
-               retval = -EINVAL;
+               ret = -EINVAL;
+               goto exit;
        }
 
-       mutex_unlock(&sabi_mutex);
-       return retval;
-}
-
-static void test_backlight(void)
-{
-       struct sabi_retval sretval;
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-
-       sabi_set_command(sabi_config->commands.set_backlight, 0);
-       printk(KERN_DEBUG "backlight should be off\n");
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-
-       msleep(1000);
+       if (out) {
+               out->d0 = readl(samsung->sabi_iface + SABI_IFACE_DATA);
+               out->d1 = readl(samsung->sabi_iface + SABI_IFACE_DATA + 4);
+               out->d2 = readw(samsung->sabi_iface + SABI_IFACE_DATA + 2);
+               out->d3 = readb(samsung->sabi_iface + SABI_IFACE_DATA + 1);
+       }
 
-       sabi_set_command(sabi_config->commands.set_backlight, 1);
-       printk(KERN_DEBUG "backlight should be on\n");
+       if (debug && out) {
+               pr_info("SABI return data:{0x%08x, 0x%08x, 0x%04x, 0x%02x}",
+                       out->d0, out->d1, out->d2, out->d3);
+       }
 
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+exit:
+       mutex_unlock(&samsung->sabi_mutex);
+       return ret;
 }
 
-static void test_wireless(void)
+/* simple wrappers usable with most commands */
+static int sabi_set_commandb(struct samsung_laptop *samsung,
+                            u16 command, u8 data)
 {
-       struct sabi_retval sretval;
+       struct sabi_data in = { { { .d0 = 0, .d1 = 0, .d2 = 0, .d3 = 0 } } };
 
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-
-       sabi_set_command(sabi_config->commands.set_wireless_button, 0);
-       printk(KERN_DEBUG "wireless led should be off\n");
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-
-       msleep(1000);
-
-       sabi_set_command(sabi_config->commands.set_wireless_button, 1);
-       printk(KERN_DEBUG "wireless led should be on\n");
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+       in.data[0] = data;
+       return sabi_command(samsung, command, &in, NULL);
 }
 
-static u8 read_brightness(void)
+static int read_brightness(struct samsung_laptop *samsung)
 {
-       struct sabi_retval sretval;
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data sretval;
        int user_brightness = 0;
        int retval;
 
-       retval = sabi_get_command(sabi_config->commands.get_brightness,
-                                 &sretval);
-       if (!retval) {
-               user_brightness = sretval.retval[0];
-               if (user_brightness > sabi_config->min_brightness)
-                       user_brightness -= sabi_config->min_brightness;
-               else
-                       user_brightness = 0;
-       }
+       retval = sabi_command(samsung, commands->get_brightness,
+                             NULL, &sretval);
+       if (retval)
+               return retval;
+
+       user_brightness = sretval.data[0];
+       if (user_brightness > config->min_brightness)
+               user_brightness -= config->min_brightness;
+       else
+               user_brightness = 0;
+
        return user_brightness;
 }
 
-static void set_brightness(u8 user_brightness)
+static void set_brightness(struct samsung_laptop *samsung, u8 user_brightness)
 {
-       u8 user_level = user_brightness + sabi_config->min_brightness;
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &samsung->config->commands;
+       u8 user_level = user_brightness + config->min_brightness;
 
-       if (has_stepping_quirk && user_level != 0) {
+       if (samsung->has_stepping_quirk && user_level != 0) {
                /*
                 * short circuit if the specified level is what's already set
                 * to prevent the screen from flickering needlessly
                 */
-               if (user_brightness == read_brightness())
+               if (user_brightness == read_brightness(samsung))
                        return;
 
-               sabi_set_command(sabi_config->commands.set_brightness, 0);
+               sabi_set_commandb(samsung, commands->set_brightness, 0);
        }
 
-       sabi_set_command(sabi_config->commands.set_brightness, user_level);
+       sabi_set_commandb(samsung, commands->set_brightness, user_level);
 }
 
 static int get_brightness(struct backlight_device *bd)
 {
-       return (int)read_brightness();
+       struct samsung_laptop *samsung = bl_get_data(bd);
+
+       return read_brightness(samsung);
 }
 
-static void check_for_stepping_quirk(void)
+static void check_for_stepping_quirk(struct samsung_laptop *samsung)
 {
-       u8 initial_level;
-       u8 check_level;
-       u8 orig_level = read_brightness();
+       int initial_level;
+       int check_level;
+       int orig_level = read_brightness(samsung);
 
        /*
         * Some laptops exhibit the strange behaviour of stepping toward
@@ -416,34 +512,38 @@ static void check_for_stepping_quirk(void)
         */
 
        if (orig_level == 0)
-               set_brightness(1);
+               set_brightness(samsung, 1);
 
-       initial_level = read_brightness();
+       initial_level = read_brightness(samsung);
 
        if (initial_level <= 2)
                check_level = initial_level + 2;
        else
                check_level = initial_level - 2;
 
-       has_stepping_quirk = false;
-       set_brightness(check_level);
+       samsung->has_stepping_quirk = false;
+       set_brightness(samsung, check_level);
 
-       if (read_brightness() != check_level) {
-               has_stepping_quirk = true;
+       if (read_brightness(samsung) != check_level) {
+               samsung->has_stepping_quirk = true;
                pr_info("enabled workaround for brightness stepping quirk\n");
        }
 
-       set_brightness(orig_level);
+       set_brightness(samsung, orig_level);
 }
 
 static int update_status(struct backlight_device *bd)
 {
-       set_brightness(bd->props.brightness);
+       struct samsung_laptop *samsung = bl_get_data(bd);
+       const struct sabi_commands *commands = &samsung->config->commands;
+
+       set_brightness(samsung, bd->props.brightness);
 
        if (bd->props.power == FB_BLANK_UNBLANK)
-               sabi_set_command(sabi_config->commands.set_backlight, 1);
+               sabi_set_commandb(samsung, commands->set_backlight, 1);
        else
-               sabi_set_command(sabi_config->commands.set_backlight, 0);
+               sabi_set_commandb(samsung, commands->set_backlight, 0);
+
        return 0;
 }
 
@@ -452,66 +552,101 @@ static const struct backlight_ops backlight_ops = {
        .update_status  = update_status,
 };
 
-static int rfkill_set(void *data, bool blocked)
+static int seclinux_rfkill_set(void *data, bool blocked)
 {
-       /* Do something with blocked...*/
-       /*
-        * blocked == false is on
-        * blocked == true is off
-        */
-       if (blocked)
-               sabi_set_command(sabi_config->commands.set_wireless_button, 0);
-       else
-               sabi_set_command(sabi_config->commands.set_wireless_button, 1);
+       struct samsung_rfkill *srfkill = data;
+       struct samsung_laptop *samsung = srfkill->samsung;
+       const struct sabi_commands *commands = &samsung->config->commands;
 
-       return 0;
+       return sabi_set_commandb(samsung, commands->set_wireless_button,
+                                !blocked);
 }
 
-static struct rfkill_ops rfkill_ops = {
-       .set_block = rfkill_set,
+static struct rfkill_ops seclinux_rfkill_ops = {
+       .set_block = seclinux_rfkill_set,
 };
 
-static int init_wireless(struct platform_device *sdev)
+static int swsmi_wireless_status(struct samsung_laptop *samsung,
+                                struct sabi_data *data)
 {
-       int retval;
+       const struct sabi_commands *commands = &samsung->config->commands;
 
-       rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN,
-                          &rfkill_ops, NULL);
-       if (!rfk)
-               return -ENOMEM;
-
-       retval = rfkill_register(rfk);
-       if (retval) {
-               rfkill_destroy(rfk);
-               return -ENODEV;
-       }
+       return sabi_command(samsung, commands->get_wireless_status,
+                           NULL, data);
+}
 
-       return 0;
+static int swsmi_rfkill_set(void *priv, bool blocked)
+{
+       struct samsung_rfkill *srfkill = priv;
+       struct samsung_laptop *samsung = srfkill->samsung;
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int ret, i;
+
+       ret = swsmi_wireless_status(samsung, &data);
+       if (ret)
+               return ret;
+
+       /* Don't set the state for non-present devices */
+       for (i = 0; i < 4; i++)
+               if (data.data[i] == 0x02)
+                       data.data[1] = 0;
+
+       if (srfkill->type == RFKILL_TYPE_WLAN)
+               data.data[WL_STATUS_WLAN] = !blocked;
+       else if (srfkill->type == RFKILL_TYPE_BLUETOOTH)
+               data.data[WL_STATUS_BT] = !blocked;
+
+       return sabi_command(samsung, commands->set_wireless_status,
+                           &data, &data);
 }
 
-static void destroy_wireless(void)
+static void swsmi_rfkill_query(struct rfkill *rfkill, void *priv)
 {
-       rfkill_unregister(rfk);
-       rfkill_destroy(rfk);
+       struct samsung_rfkill *srfkill = priv;
+       struct samsung_laptop *samsung = srfkill->samsung;
+       struct sabi_data data;
+       int ret;
+
+       ret = swsmi_wireless_status(samsung, &data);
+       if (ret)
+               return ;
+
+       if (srfkill->type == RFKILL_TYPE_WLAN)
+               ret = data.data[WL_STATUS_WLAN];
+       else if (srfkill->type == RFKILL_TYPE_BLUETOOTH)
+               ret = data.data[WL_STATUS_BT];
+       else
+               return ;
+
+       rfkill_set_sw_state(rfkill, !ret);
 }
 
+static struct rfkill_ops swsmi_rfkill_ops = {
+       .set_block = swsmi_rfkill_set,
+       .query = swsmi_rfkill_query,
+};
+
 static ssize_t get_performance_level(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct sabi_retval sretval;
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &config->commands;
+       struct sabi_data sretval;
        int retval;
        int i;
 
        /* Read the state */
-       retval = sabi_get_command(sabi_config->commands.get_performance_level,
-                                 &sretval);
+       retval = sabi_command(samsung, commands->get_performance_level,
+                             NULL, &sretval);
        if (retval)
                return retval;
 
        /* The logic is backwards, yeah, lots of fun... */
-       for (i = 0; sabi_config->performance_levels[i].name; ++i) {
-               if (sretval.retval[0] == sabi_config->performance_levels[i].value)
-                       return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
+       for (i = 0; config->performance_levels[i].name; ++i) {
+               if (sretval.data[0] == config->performance_levels[i].value)
+                       return sprintf(buf, "%s\n", config->performance_levels[i].name);
        }
        return sprintf(buf, "%s\n", "unknown");
 }
@@ -520,280 +655,189 @@ static ssize_t set_performance_level(struct device *dev,
                                struct device_attribute *attr, const char *buf,
                                size_t count)
 {
-       if (count >= 1) {
-               int i;
-               for (i = 0; sabi_config->performance_levels[i].name; ++i) {
-                       const struct sabi_performance_level *level =
-                               &sabi_config->performance_levels[i];
-                       if (!strncasecmp(level->name, buf, strlen(level->name))) {
-                               sabi_set_command(sabi_config->commands.set_performance_level,
-                                                level->value);
-                               break;
-                       }
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &config->commands;
+       int i;
+
+       if (count < 1)
+               return count;
+
+       for (i = 0; config->performance_levels[i].name; ++i) {
+               const struct sabi_performance_level *level =
+                       &config->performance_levels[i];
+               if (!strncasecmp(level->name, buf, strlen(level->name))) {
+                       sabi_set_commandb(samsung,
+                                         commands->set_performance_level,
+                                         level->value);
+                       break;
                }
-               if (!sabi_config->performance_levels[i].name)
-                       return -EINVAL;
        }
+
+       if (!config->performance_levels[i].name)
+               return -EINVAL;
+
        return count;
 }
+
 static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
                   get_performance_level, set_performance_level);
 
-
-static int __init dmi_check_cb(const struct dmi_system_id *id)
+static int read_battery_life_extender(struct samsung_laptop *samsung)
 {
-       pr_info("found laptop model '%s'\n",
-               id->ident);
-       return 1;
-}
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
 
-static struct dmi_system_id __initdata samsung_dmi_table[] = {
-       {
-               .ident = "N128",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N128"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N130",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N130"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N510",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N510"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "X125",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X125"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "X120/X170",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NC10",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NC10"),
-               },
-               .callback = dmi_check_cb,
-       },
-               {
-               .ident = "NP-Q45",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
-                       DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
-               },
-               .callback = dmi_check_cb,
-               },
-       {
-               .ident = "X360",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X360"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R410 Plus",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R460"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R518",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R518"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R519/R719",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150/N210/N220",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N220",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N220"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N220"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150/N210/N220/N230",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150P/N210P/N220P",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R700",
-               .matches = {
-                     DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                     DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
-                     DMI_MATCH(DMI_BOARD_NAME, "SR700"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R530/R730",
-               .matches = {
-                     DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                     DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
-                     DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NF110/NF210/NF310",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N145P/N250P/N260P",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R70/R71",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "P460",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
-                       DMI_MATCH(DMI_BOARD_NAME, "P460"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R528/R728",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NC210/NC110",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
-               },
-               .callback = dmi_check_cb,
-       },
-               {
-               .ident = "X520",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X520"),
-               },
-               .callback = dmi_check_cb,
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+       if (commands->get_battery_life_extender == 0xFFFF)
+               return -ENODEV;
 
-static int find_signature(void __iomem *memcheck, const char *testStr)
-{
-       int i = 0;
-       int loca;
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80;
+       retval = sabi_command(samsung, commands->get_battery_life_extender,
+                             &data, &data);
 
-       for (loca = 0; loca < 0xffff; loca++) {
-               char temp = readb(memcheck + loca);
+       if (retval)
+               return retval;
 
-               if (temp == testStr[i]) {
-                       if (i == strlen(testStr)-1)
+       if (data.data[0] != 0 && data.data[0] != 1)
+               return -ENODEV;
+
+       return data.data[0];
+}
+
+static int write_battery_life_extender(struct samsung_laptop *samsung,
+                                      int enabled)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80 | enabled;
+       return sabi_command(samsung, commands->set_battery_life_extender,
+                           &data, NULL);
+}
+
+static ssize_t get_battery_life_extender(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret;
+
+       ret = read_battery_life_extender(samsung);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_battery_life_extender(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret, value;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+
+       ret = write_battery_life_extender(samsung, !!value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(battery_life_extender, S_IWUSR | S_IRUGO,
+                  get_battery_life_extender, set_battery_life_extender);
+
+static int read_usb_charge(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
+
+       if (commands->get_usb_charge == 0xFFFF)
+               return -ENODEV;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80;
+       retval = sabi_command(samsung, commands->get_usb_charge,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       if (data.data[0] != 0 && data.data[0] != 1)
+               return -ENODEV;
+
+       return data.data[0];
+}
+
+static int write_usb_charge(struct samsung_laptop *samsung,
+                           int enabled)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80 | enabled;
+       return sabi_command(samsung, commands->set_usb_charge,
+                           &data, NULL);
+}
+
+static ssize_t get_usb_charge(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret;
+
+       ret = read_usb_charge(samsung);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_usb_charge(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret, value;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+
+       ret = write_usb_charge(samsung, !!value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(usb_charge, S_IWUSR | S_IRUGO,
+                  get_usb_charge, set_usb_charge);
+
+static struct attribute *platform_attributes[] = {
+       &dev_attr_performance_level.attr,
+       &dev_attr_battery_life_extender.attr,
+       &dev_attr_usb_charge.attr,
+       NULL
+};
+
+static int find_signature(void __iomem *memcheck, const char *testStr)
+{
+       int i = 0;
+       int loca;
+
+       for (loca = 0; loca < 0xffff; loca++) {
+               char temp = readb(memcheck + loca);
+
+               if (temp == testStr[i]) {
+                       if (i == strlen(testStr)-1)
                                break;
                        ++i;
                } else {
@@ -803,153 +847,772 @@ static int find_signature(void __iomem *memcheck, const char *testStr)
        return loca;
 }
 
-static int __init samsung_init(void)
+static void samsung_rfkill_exit(struct samsung_laptop *samsung)
 {
-       struct backlight_properties props;
-       struct sabi_retval sretval;
-       unsigned int ifaceP;
-       int i;
-       int loca;
+       if (samsung->wlan.rfkill) {
+               rfkill_unregister(samsung->wlan.rfkill);
+               rfkill_destroy(samsung->wlan.rfkill);
+               samsung->wlan.rfkill = NULL;
+       }
+       if (samsung->bluetooth.rfkill) {
+               rfkill_unregister(samsung->bluetooth.rfkill);
+               rfkill_destroy(samsung->bluetooth.rfkill);
+               samsung->bluetooth.rfkill = NULL;
+       }
+}
+
+static int samsung_new_rfkill(struct samsung_laptop *samsung,
+                             struct samsung_rfkill *arfkill,
+                             const char *name, enum rfkill_type type,
+                             const struct rfkill_ops *ops,
+                             int blocked)
+{
+       struct rfkill **rfkill = &arfkill->rfkill;
+       int ret;
+
+       arfkill->type = type;
+       arfkill->samsung = samsung;
+
+       *rfkill = rfkill_alloc(name, &samsung->platform_device->dev,
+                              type, ops, arfkill);
+
+       if (!*rfkill)
+               return -EINVAL;
+
+       if (blocked != -1)
+               rfkill_init_sw_state(*rfkill, blocked);
+
+       ret = rfkill_register(*rfkill);
+       if (ret) {
+               rfkill_destroy(*rfkill);
+               *rfkill = NULL;
+               return ret;
+       }
+       return 0;
+}
+
+static int __init samsung_rfkill_init_seclinux(struct samsung_laptop *samsung)
+{
+       return samsung_new_rfkill(samsung, &samsung->wlan, "samsung-wlan",
+                                 RFKILL_TYPE_WLAN, &seclinux_rfkill_ops, -1);
+}
+
+static int __init samsung_rfkill_init_swsmi(struct samsung_laptop *samsung)
+{
+       struct sabi_data data;
+       int ret;
+
+       ret = swsmi_wireless_status(samsung, &data);
+       if (ret) {
+               /* Some swsmi laptops use the old seclinux way to control
+                * wireless devices */
+               if (ret == -EINVAL)
+                       ret = samsung_rfkill_init_seclinux(samsung);
+               return ret;
+       }
+
+       /* 0x02 seems to mean that the device is no present/available */
+
+       if (data.data[WL_STATUS_WLAN] != 0x02)
+               ret = samsung_new_rfkill(samsung, &samsung->wlan,
+                                        "samsung-wlan",
+                                        RFKILL_TYPE_WLAN,
+                                        &swsmi_rfkill_ops,
+                                        !data.data[WL_STATUS_WLAN]);
+       if (ret)
+               goto exit;
+
+       if (data.data[WL_STATUS_BT] != 0x02)
+               ret = samsung_new_rfkill(samsung, &samsung->bluetooth,
+                                        "samsung-bluetooth",
+                                        RFKILL_TYPE_BLUETOOTH,
+                                        &swsmi_rfkill_ops,
+                                        !data.data[WL_STATUS_BT]);
+       if (ret)
+               goto exit;
+
+exit:
+       if (ret)
+               samsung_rfkill_exit(samsung);
+
+       return ret;
+}
+
+static int __init samsung_rfkill_init(struct samsung_laptop *samsung)
+{
+       if (samsung->config->sabi_version == 2)
+               return samsung_rfkill_init_seclinux(samsung);
+       if (samsung->config->sabi_version == 3)
+               return samsung_rfkill_init_swsmi(samsung);
+       return 0;
+}
+
+static int kbd_backlight_enable(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
        int retval;
 
-       mutex_init(&sabi_mutex);
+       if (commands->kbd_backlight == 0xFFFF)
+               return -ENODEV;
 
-       if (!force && !dmi_check_system(samsung_dmi_table))
+       memset(&data, 0, sizeof(data));
+       data.d0 = 0xaabb;
+       retval = sabi_command(samsung, commands->kbd_backlight,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       if (data.d0 != 0xccdd)
                return -ENODEV;
+       return 0;
+}
 
-       f0000_segment = ioremap_nocache(0xf0000, 0xffff);
-       if (!f0000_segment) {
-               pr_err("Can't map the segment at 0xf0000\n");
-               return -EINVAL;
+static int kbd_backlight_read(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x81;
+       retval = sabi_command(samsung, commands->kbd_backlight,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       return data.data[0];
+}
+
+static int kbd_backlight_write(struct samsung_laptop *samsung, int brightness)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.d0 = 0x82 | ((brightness & 0xFF) << 8);
+       return sabi_command(samsung, commands->kbd_backlight,
+                           &data, NULL);
+}
+
+static void kbd_led_update(struct work_struct *work)
+{
+       struct samsung_laptop *samsung;
+
+       samsung = container_of(work, struct samsung_laptop, kbd_led_work);
+       kbd_backlight_write(samsung, samsung->kbd_led_wk);
+}
+
+static void kbd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       struct samsung_laptop *samsung;
+
+       samsung = container_of(led_cdev, struct samsung_laptop, kbd_led);
+
+       if (value > samsung->kbd_led.max_brightness)
+               value = samsung->kbd_led.max_brightness;
+       else if (value < 0)
+               value = 0;
+
+       samsung->kbd_led_wk = value;
+       queue_work(samsung->led_workqueue, &samsung->kbd_led_work);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+       struct samsung_laptop *samsung;
+
+       samsung = container_of(led_cdev, struct samsung_laptop, kbd_led);
+       return kbd_backlight_read(samsung);
+}
+
+static void samsung_leds_exit(struct samsung_laptop *samsung)
+{
+       if (!IS_ERR_OR_NULL(samsung->kbd_led.dev))
+               led_classdev_unregister(&samsung->kbd_led);
+       if (samsung->led_workqueue)
+               destroy_workqueue(samsung->led_workqueue);
+}
+
+static int __init samsung_leds_init(struct samsung_laptop *samsung)
+{
+       int ret = 0;
+
+       samsung->led_workqueue = create_singlethread_workqueue("led_workqueue");
+       if (!samsung->led_workqueue)
+               return -ENOMEM;
+
+       if (kbd_backlight_enable(samsung) >= 0) {
+               INIT_WORK(&samsung->kbd_led_work, kbd_led_update);
+
+               samsung->kbd_led.name = "samsung::kbd_backlight";
+               samsung->kbd_led.brightness_set = kbd_led_set;
+               samsung->kbd_led.brightness_get = kbd_led_get;
+               samsung->kbd_led.max_brightness = 8;
+
+               ret = led_classdev_register(&samsung->platform_device->dev,
+                                          &samsung->kbd_led);
+       }
+
+       if (ret)
+               samsung_leds_exit(samsung);
+
+       return ret;
+}
+
+static void samsung_backlight_exit(struct samsung_laptop *samsung)
+{
+       if (samsung->backlight_device) {
+               backlight_device_unregister(samsung->backlight_device);
+               samsung->backlight_device = NULL;
+       }
+}
+
+static int __init samsung_backlight_init(struct samsung_laptop *samsung)
+{
+       struct backlight_device *bd;
+       struct backlight_properties props;
+
+       if (!samsung->handle_backlight)
+               return 0;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = samsung->config->max_brightness -
+               samsung->config->min_brightness;
+
+       bd = backlight_device_register("samsung",
+                                      &samsung->platform_device->dev,
+                                      samsung, &backlight_ops,
+                                      &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
+
+       samsung->backlight_device = bd;
+       samsung->backlight_device->props.brightness = read_brightness(samsung);
+       samsung->backlight_device->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(samsung->backlight_device);
+
+       return 0;
+}
+
+static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
+                                      struct attribute *attr, int idx)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct samsung_laptop *samsung = platform_get_drvdata(pdev);
+       bool ok = true;
+
+       if (attr == &dev_attr_performance_level.attr)
+               ok = !!samsung->config->performance_levels[0].name;
+       if (attr == &dev_attr_battery_life_extender.attr)
+               ok = !!(read_battery_life_extender(samsung) >= 0);
+       if (attr == &dev_attr_usb_charge.attr)
+               ok = !!(read_usb_charge(samsung) >= 0);
+
+       return ok ? attr->mode : 0;
+}
+
+static struct attribute_group platform_attribute_group = {
+       .is_visible = samsung_sysfs_is_visible,
+       .attrs = platform_attributes
+};
+
+static void samsung_sysfs_exit(struct samsung_laptop *samsung)
+{
+       struct platform_device *device = samsung->platform_device;
+
+       sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
+}
+
+static int __init samsung_sysfs_init(struct samsung_laptop *samsung)
+{
+       struct platform_device *device = samsung->platform_device;
+
+       return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
+
+}
+
+static int show_call(struct seq_file *m, void *data)
+{
+       struct samsung_laptop *samsung = m->private;
+       struct sabi_data *sdata = &samsung->debug.data;
+       int ret;
+
+       seq_printf(m, "SABI 0x%04x {0x%08x, 0x%08x, 0x%04x, 0x%02x}\n",
+                  samsung->debug.command,
+                  sdata->d0, sdata->d1, sdata->d2, sdata->d3);
+
+       ret = sabi_command(samsung, samsung->debug.command, sdata, sdata);
+
+       if (ret) {
+               seq_printf(m, "SABI command 0x%04x failed\n",
+                          samsung->debug.command);
+               return ret;
+       }
+
+       seq_printf(m, "SABI {0x%08x, 0x%08x, 0x%04x, 0x%02x}\n",
+                  sdata->d0, sdata->d1, sdata->d2, sdata->d3);
+       return 0;
+}
+
+static int samsung_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_call, inode->i_private);
+}
+
+static const struct file_operations samsung_laptop_call_io_ops = {
+       .owner = THIS_MODULE,
+       .open = samsung_debugfs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static void samsung_debugfs_exit(struct samsung_laptop *samsung)
+{
+       debugfs_remove_recursive(samsung->debug.root);
+}
+
+static int samsung_debugfs_init(struct samsung_laptop *samsung)
+{
+       struct dentry *dent;
+
+       samsung->debug.root = debugfs_create_dir("samsung-laptop", NULL);
+       if (!samsung->debug.root) {
+               pr_err("failed to create debugfs directory");
+               goto error_debugfs;
        }
 
+       samsung->debug.f0000_wrapper.data = samsung->f0000_segment;
+       samsung->debug.f0000_wrapper.size = 0xffff;
+
+       samsung->debug.data_wrapper.data = &samsung->debug.data;
+       samsung->debug.data_wrapper.size = sizeof(samsung->debug.data);
+
+       samsung->debug.sdiag_wrapper.data = samsung->sdiag;
+       samsung->debug.sdiag_wrapper.size = strlen(samsung->sdiag);
+
+       dent = debugfs_create_u16("command", S_IRUGO | S_IWUSR,
+                                 samsung->debug.root, &samsung->debug.command);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u32("d0", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                 &samsung->debug.data.d0);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u32("d1", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                 &samsung->debug.data.d1);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u16("d2", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                 &samsung->debug.data.d2);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u8("d3", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                &samsung->debug.data.d3);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_blob("data", S_IRUGO | S_IWUSR,
+                                  samsung->debug.root,
+                                  &samsung->debug.data_wrapper);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_blob("f0000_segment", S_IRUSR | S_IWUSR,
+                                  samsung->debug.root,
+                                  &samsung->debug.f0000_wrapper);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_file("call", S_IFREG | S_IRUGO,
+                                  samsung->debug.root, samsung,
+                                  &samsung_laptop_call_io_ops);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_blob("sdiag", S_IRUGO | S_IWUSR,
+                                  samsung->debug.root,
+                                  &samsung->debug.sdiag_wrapper);
+       if (!dent)
+               goto error_debugfs;
+
+       return 0;
+
+error_debugfs:
+       samsung_debugfs_exit(samsung);
+       return -ENOMEM;
+}
+
+static void samsung_sabi_exit(struct samsung_laptop *samsung)
+{
+       const struct sabi_config *config = samsung->config;
+
+       /* Turn off "Linux" mode in the BIOS */
+       if (config && config->commands.set_linux != 0xff)
+               sabi_set_commandb(samsung, config->commands.set_linux, 0x80);
+
+       if (samsung->sabi_iface) {
+               iounmap(samsung->sabi_iface);
+               samsung->sabi_iface = NULL;
+       }
+       if (samsung->f0000_segment) {
+               iounmap(samsung->f0000_segment);
+               samsung->f0000_segment = NULL;
+       }
+
+       samsung->config = NULL;
+}
+
+static __init void samsung_sabi_infos(struct samsung_laptop *samsung, int loca,
+                                     unsigned int ifaceP)
+{
+       const struct sabi_config *config = samsung->config;
+
+       printk(KERN_DEBUG "This computer supports SABI==%x\n",
+              loca + 0xf0000 - 6);
+
+       printk(KERN_DEBUG "SABI header:\n");
+       printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
+              readw(samsung->sabi + config->header_offsets.port));
+       printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
+              readb(samsung->sabi + config->header_offsets.iface_func));
+       printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
+              readb(samsung->sabi + config->header_offsets.en_mem));
+       printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
+              readb(samsung->sabi + config->header_offsets.re_mem));
+       printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
+              readw(samsung->sabi + config->header_offsets.data_offset));
+       printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
+              readw(samsung->sabi + config->header_offsets.data_segment));
+
+       printk(KERN_DEBUG " SABI pointer = 0x%08x\n", ifaceP);
+}
+
+static void __init samsung_sabi_diag(struct samsung_laptop *samsung)
+{
+       int loca = find_signature(samsung->f0000_segment, "SDiaG@");
+       int i;
+
+       if (loca == 0xffff)
+               return ;
+
+       /* Example:
+        * Ident: @SDiaG@686XX-N90X3A/966-SEC-07HL-S90X3A
+        *
+        * Product name: 90X3A
+        * BIOS Version: 07HL
+        */
+       loca += 1;
+       for (i = 0; loca < 0xffff && i < sizeof(samsung->sdiag) - 1; loca++) {
+               char temp = readb(samsung->f0000_segment + loca);
+
+               if (isalnum(temp) || temp == '/' || temp == '-')
+                       samsung->sdiag[i++] = temp;
+               else
+                       break ;
+       }
+
+       if (debug && samsung->sdiag[0])
+               pr_info("sdiag: %s", samsung->sdiag);
+}
+
+static int __init samsung_sabi_init(struct samsung_laptop *samsung)
+{
+       const struct sabi_config *config = NULL;
+       const struct sabi_commands *commands;
+       unsigned int ifaceP;
+       int ret = 0;
+       int i;
+       int loca;
+
+       samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff);
+       if (!samsung->f0000_segment) {
+               if (debug || force)
+                       pr_err("Can't map the segment at 0xf0000\n");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       samsung_sabi_diag(samsung);
+
        /* Try to find one of the signatures in memory to find the header */
        for (i = 0; sabi_configs[i].test_string != 0; ++i) {
-               sabi_config = &sabi_configs[i];
-               loca = find_signature(f0000_segment, sabi_config->test_string);
+               samsung->config = &sabi_configs[i];
+               loca = find_signature(samsung->f0000_segment,
+                                     samsung->config->test_string);
                if (loca != 0xffff)
                        break;
        }
 
        if (loca == 0xffff) {
-               pr_err("This computer does not support SABI\n");
-               goto error_no_signature;
+               if (debug || force)
+                       pr_err("This computer does not support SABI\n");
+               ret = -ENODEV;
+               goto exit;
        }
 
+       config = samsung->config;
+       commands = &config->commands;
+
        /* point to the SMI port Number */
        loca += 1;
-       sabi = (f0000_segment + loca);
-
-       if (debug) {
-               printk(KERN_DEBUG "This computer supports SABI==%x\n",
-                       loca + 0xf0000 - 6);
-               printk(KERN_DEBUG "SABI header:\n");
-               printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.port));
-               printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.iface_func));
-               printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.en_mem));
-               printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.re_mem));
-               printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.data_offset));
-               printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.data_segment));
-       }
+       samsung->sabi = (samsung->f0000_segment + loca);
 
        /* Get a pointer to the SABI Interface */
-       ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
-       ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
-       sabi_iface = ioremap_nocache(ifaceP, 16);
-       if (!sabi_iface) {
-               pr_err("Can't remap %x\n", ifaceP);
-               goto error_no_signature;
-       }
-       if (debug) {
-               printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
-               printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
+       ifaceP = (readw(samsung->sabi + config->header_offsets.data_segment) & 0x0ffff) << 4;
+       ifaceP += readw(samsung->sabi + config->header_offsets.data_offset) & 0x0ffff;
 
-               test_backlight();
-               test_wireless();
+       if (debug)
+               samsung_sabi_infos(samsung, loca, ifaceP);
 
-               retval = sabi_get_command(sabi_config->commands.get_brightness,
-                                         &sretval);
-               printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
+       samsung->sabi_iface = ioremap_nocache(ifaceP, 16);
+       if (!samsung->sabi_iface) {
+               pr_err("Can't remap %x\n", ifaceP);
+               ret = -EINVAL;
+               goto exit;
        }
 
        /* Turn on "Linux" mode in the BIOS */
-       if (sabi_config->commands.set_linux != 0xff) {
-               retval = sabi_set_command(sabi_config->commands.set_linux,
-                                         0x81);
+       if (commands->set_linux != 0xff) {
+               int retval = sabi_set_commandb(samsung,
+                                              commands->set_linux, 0x81);
                if (retval) {
                        pr_warn("Linux mode was not set!\n");
-                       goto error_no_platform;
+                       ret = -ENODEV;
+                       goto exit;
                }
        }
 
        /* Check for stepping quirk */
-       check_for_stepping_quirk();
+       if (samsung->handle_backlight)
+               check_for_stepping_quirk(samsung);
 
-       /* knock up a platform device to hang stuff off of */
-       sdev = platform_device_register_simple("samsung", -1, NULL, 0);
-       if (IS_ERR(sdev))
-               goto error_no_platform;
+       pr_info("detected SABI interface: %s\n",
+               samsung->config->test_string);
 
-       /* create a backlight device to talk to this one */
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_PLATFORM;
-       props.max_brightness = sabi_config->max_brightness -
-                               sabi_config->min_brightness;
-       backlight_device = backlight_device_register("samsung", &sdev->dev,
-                                                    NULL, &backlight_ops,
-                                                    &props);
-       if (IS_ERR(backlight_device))
-               goto error_no_backlight;
-
-       backlight_device->props.brightness = read_brightness();
-       backlight_device->props.power = FB_BLANK_UNBLANK;
-       backlight_update_status(backlight_device);
-
-       retval = init_wireless(sdev);
-       if (retval)
-               goto error_no_rfk;
+exit:
+       if (ret)
+               samsung_sabi_exit(samsung);
 
-       retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
-       if (retval)
-               goto error_file_create;
+       return ret;
+}
+
+static void samsung_platform_exit(struct samsung_laptop *samsung)
+{
+       if (samsung->platform_device) {
+               platform_device_unregister(samsung->platform_device);
+               samsung->platform_device = NULL;
+       }
+}
+
+static int __init samsung_platform_init(struct samsung_laptop *samsung)
+{
+       struct platform_device *pdev;
 
+       pdev = platform_device_register_simple("samsung", -1, NULL, 0);
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
+
+       samsung->platform_device = pdev;
+       platform_set_drvdata(samsung->platform_device, samsung);
        return 0;
+}
 
-error_file_create:
-       destroy_wireless();
+static struct samsung_quirks *quirks;
 
-error_no_rfk:
-       backlight_device_unregister(backlight_device);
+static int __init samsung_dmi_matched(const struct dmi_system_id *d)
+{
+       quirks = d->driver_data;
+       return 0;
+}
 
-error_no_backlight:
-       platform_device_unregister(sdev);
+static struct dmi_system_id __initdata samsung_dmi_table[] = {
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
+               },
+       },
+       /* Specific DMI ids for laptop with quirks */
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N150P",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
+               DMI_MATCH(DMI_BOARD_NAME, "N150P"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N145P/N250P/N260P",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
+               DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N150/N210/N220",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
+               DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "NF110/NF210/NF310",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
+               DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+
+static struct platform_device *samsung_platform_device;
+
+static int __init samsung_init(void)
+{
+       struct samsung_laptop *samsung;
+       int ret;
+
+       quirks = &samsung_unknown;
+       if (!force && !dmi_check_system(samsung_dmi_table))
+               return -ENODEV;
+
+       samsung = kzalloc(sizeof(*samsung), GFP_KERNEL);
+       if (!samsung)
+               return -ENOMEM;
+
+       mutex_init(&samsung->sabi_mutex);
+       samsung->handle_backlight = true;
+       samsung->quirks = quirks;
 
-error_no_platform:
-       iounmap(sabi_iface);
 
-error_no_signature:
-       iounmap(f0000_segment);
-       return -EINVAL;
+#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
+       /* Don't handle backlight here if the acpi video already handle it */
+       if (acpi_video_backlight_support()) {
+               if (samsung->quirks->broken_acpi_video) {
+                       pr_info("Disabling ACPI video driver\n");
+                       acpi_video_unregister();
+               } else {
+                       samsung->handle_backlight = false;
+               }
+       }
+#endif
+
+       ret = samsung_platform_init(samsung);
+       if (ret)
+               goto error_platform;
+
+       ret = samsung_sabi_init(samsung);
+       if (ret)
+               goto error_sabi;
+
+#ifdef CONFIG_ACPI
+       /* Only log that if we are really on a sabi platform */
+       if (acpi_video_backlight_support() &&
+           !samsung->quirks->broken_acpi_video)
+               pr_info("Backlight controlled by ACPI video driver\n");
+#endif
+
+       ret = samsung_sysfs_init(samsung);
+       if (ret)
+               goto error_sysfs;
+
+       ret = samsung_backlight_init(samsung);
+       if (ret)
+               goto error_backlight;
+
+       ret = samsung_rfkill_init(samsung);
+       if (ret)
+               goto error_rfkill;
+
+       ret = samsung_leds_init(samsung);
+       if (ret)
+               goto error_leds;
+
+       ret = samsung_debugfs_init(samsung);
+       if (ret)
+               goto error_debugfs;
+
+       samsung_platform_device = samsung->platform_device;
+       return ret;
+
+error_debugfs:
+       samsung_leds_exit(samsung);
+error_leds:
+       samsung_rfkill_exit(samsung);
+error_rfkill:
+       samsung_backlight_exit(samsung);
+error_backlight:
+       samsung_sysfs_exit(samsung);
+error_sysfs:
+       samsung_sabi_exit(samsung);
+error_sabi:
+       samsung_platform_exit(samsung);
+error_platform:
+       kfree(samsung);
+       return ret;
 }
 
 static void __exit samsung_exit(void)
 {
-       /* Turn off "Linux" mode in the BIOS */
-       if (sabi_config->commands.set_linux != 0xff)
-               sabi_set_command(sabi_config->commands.set_linux, 0x80);
-
-       device_remove_file(&sdev->dev, &dev_attr_performance_level);
-       backlight_device_unregister(backlight_device);
-       destroy_wireless();
-       iounmap(sabi_iface);
-       iounmap(f0000_segment);
-       platform_device_unregister(sdev);
+       struct samsung_laptop *samsung;
+
+       samsung = platform_get_drvdata(samsung_platform_device);
+
+       samsung_debugfs_exit(samsung);
+       samsung_leds_exit(samsung);
+       samsung_rfkill_exit(samsung);
+       samsung_backlight_exit(samsung);
+       samsung_sysfs_exit(samsung);
+       samsung_sabi_exit(samsung);
+       samsung_platform_exit(samsung);
+
+       kfree(samsung);
+       samsung_platform_device = NULL;
 }
 
 module_init(samsung_init);
index c006dee5ebfe84bb33a962dbdddf4ff9440c74be..8a51795aa02a07bbc0d60b6267686ca4f54dbe9b 100644 (file)
@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor,
                 "default is -1 (automatic)");
 #endif
 
-static int kbd_backlight;      /* = 1 */
+static int kbd_backlight = 1;
 module_param(kbd_backlight, int, 0444);
 MODULE_PARM_DESC(kbd_backlight,
                 "set this to 0 to disable keyboard backlight, "
@@ -347,6 +347,7 @@ static void sony_laptop_report_input_event(u8 event)
        struct input_dev *jog_dev = sony_laptop_input.jog_dev;
        struct input_dev *key_dev = sony_laptop_input.key_dev;
        struct sony_laptop_keypress kp = { NULL };
+       int scancode = -1;
 
        if (event == SONYPI_EVENT_FNKEY_RELEASED ||
                        event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
@@ -380,8 +381,8 @@ static void sony_laptop_report_input_event(u8 event)
                        dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
                        break;
                }
-               if (sony_laptop_input_index[event] != -1) {
-                       kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
+               if ((scancode = sony_laptop_input_index[event]) != -1) {
+                       kp.key = sony_laptop_input_keycode_map[scancode];
                        if (kp.key != KEY_UNKNOWN)
                                kp.dev = key_dev;
                }
@@ -389,9 +390,11 @@ static void sony_laptop_report_input_event(u8 event)
        }
 
        if (kp.dev) {
+               /* if we have a scancode we emit it so we can always
+                   remap the key */
+               if (scancode != -1)
+                       input_event(kp.dev, EV_MSC, MSC_SCAN, scancode);
                input_report_key(kp.dev, kp.key, 1);
-               /* we emit the scancode so we can always remap the key */
-               input_event(kp.dev, EV_MSC, MSC_SCAN, event);
                input_sync(kp.dev);
 
                /* schedule key release */
@@ -466,7 +469,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
        jog_dev->name = "Sony Vaio Jogdial";
        jog_dev->id.bustype = BUS_ISA;
        jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
-       key_dev->dev.parent = &acpi_device->dev;
+       jog_dev->dev.parent = &acpi_device->dev;
 
        input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
        input_set_capability(jog_dev, EV_REL, REL_WHEEL);
index ea0c6075b72012458f099bfd6fb013415e7d85e1..d68c0002f4a29c451116422b4693ab2e330f7160 100644 (file)
@@ -8658,7 +8658,7 @@ static int __must_check __init get_thinkpad_model_data(
        }
 
        s = dmi_get_system_info(DMI_PRODUCT_VERSION);
-       if (s && !strnicmp(s, "ThinkPad", 8)) {
+       if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) {
                tp->model_str = kstrdup(s, GFP_KERNEL);
                if (!tp->model_str)
                        return -ENOMEM;
index dcdc1f4a4624d782d35f3776d1a69bbfdf983cdb..ee79ce64d9dfbdb8a99061f59232325b8c57f6d3 100644 (file)
@@ -52,6 +52,8 @@
 #include <linux/input/sparse-keymap.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/i8042.h>
 
 #include <asm/uaccess.h>
 
@@ -61,6 +63,11 @@ MODULE_AUTHOR("John Belmonte");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
 MODULE_LICENSE("GPL");
 
+#define TOSHIBA_WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"
+
+/* Scan code for Fn key on TOS1900 models */
+#define TOS1900_FN_SCAN                0x6e
+
 /* Toshiba ACPI method paths */
 #define METHOD_VIDEO_OUT       "\\_SB_.VALX.DSSX"
 
@@ -95,6 +102,8 @@ MODULE_LICENSE("GPL");
 #define HCI_WIRELESS                   0x0056
 
 /* field definitions */
+#define HCI_HOTKEY_DISABLE             0x0b
+#define HCI_HOTKEY_ENABLE              0x09
 #define HCI_LCD_BRIGHTNESS_BITS                3
 #define HCI_LCD_BRIGHTNESS_SHIFT       (16-HCI_LCD_BRIGHTNESS_BITS)
 #define HCI_LCD_BRIGHTNESS_LEVELS      (1 << HCI_LCD_BRIGHTNESS_BITS)
@@ -111,6 +120,7 @@ struct toshiba_acpi_dev {
        const char *method_hci;
        struct rfkill *bt_rfk;
        struct input_dev *hotkey_dev;
+       struct work_struct hotkey_work;
        struct backlight_device *backlight_dev;
        struct led_classdev led_dev;
 
@@ -118,14 +128,18 @@ struct toshiba_acpi_dev {
        int last_key_event;
        int key_event_valid;
 
-       int illumination_supported:1;
-       int video_supported:1;
-       int fan_supported:1;
-       int system_event_supported:1;
+       unsigned int illumination_supported:1;
+       unsigned int video_supported:1;
+       unsigned int fan_supported:1;
+       unsigned int system_event_supported:1;
+       unsigned int ntfy_supported:1;
+       unsigned int info_supported:1;
 
        struct mutex mutex;
 };
 
+static struct toshiba_acpi_dev *toshiba_acpi;
+
 static const struct acpi_device_id toshiba_device_ids[] = {
        {"TOS6200", 0},
        {"TOS6208", 0},
@@ -138,6 +152,8 @@ static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
        { KE_KEY, 0x101, { KEY_MUTE } },
        { KE_KEY, 0x102, { KEY_ZOOMOUT } },
        { KE_KEY, 0x103, { KEY_ZOOMIN } },
+       { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
+       { KE_KEY, 0x139, { KEY_ZOOMRESET } },
        { KE_KEY, 0x13b, { KEY_COFFEE } },
        { KE_KEY, 0x13c, { KEY_BATTERY } },
        { KE_KEY, 0x13d, { KEY_SLEEP } },
@@ -146,7 +162,7 @@ static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
        { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
        { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0x142, { KEY_WLAN } },
-       { KE_KEY, 0x143, { KEY_PROG1 } },
+       { KE_KEY, 0x143, { KEY_TOUCHPAD_TOGGLE } },
        { KE_KEY, 0x17f, { KEY_FN } },
        { KE_KEY, 0xb05, { KEY_PROG2 } },
        { KE_KEY, 0xb06, { KEY_WWW } },
@@ -156,6 +172,7 @@ static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
        { KE_KEY, 0xb32, { KEY_NEXTSONG } },
        { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
        { KE_KEY, 0xb5a, { KEY_MEDIA } },
+       { KE_IGNORE, 0x1430, { KEY_RESERVED } },
        { KE_END, 0 },
 };
 
@@ -847,10 +864,78 @@ static const struct backlight_ops toshiba_backlight_data = {
         .update_status  = set_lcd_status,
 };
 
+static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
+                                     struct serio *port)
+{
+       if (str & 0x20)
+               return false;
+
+       if (unlikely(data == 0xe0))
+               return false;
+
+       if ((data & 0x7f) == TOS1900_FN_SCAN) {
+               schedule_work(&toshiba_acpi->hotkey_work);
+               return true;
+       }
+
+       return false;
+}
+
+static void toshiba_acpi_hotkey_work(struct work_struct *work)
+{
+       acpi_handle ec_handle = ec_get_handle();
+       acpi_status status;
+
+       if (!ec_handle)
+               return;
+
+       status = acpi_evaluate_object(ec_handle, "NTFY", NULL, NULL);
+       if (ACPI_FAILURE(status))
+               pr_err("ACPI NTFY method execution failed\n");
+}
+
+/*
+ * Returns hotkey scancode, or < 0 on failure.
+ */
+static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
+{
+       struct acpi_buffer buf;
+       union acpi_object out_obj;
+       acpi_status status;
+
+       buf.pointer = &out_obj;
+       buf.length = sizeof(out_obj);
+
+       status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO",
+                                     NULL, &buf);
+       if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) {
+               pr_err("ACPI INFO method execution failed\n");
+               return -EIO;
+       }
+
+       return out_obj.integer.value;
+}
+
+static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
+                                      int scancode)
+{
+       if (scancode == 0x100)
+               return;
+
+       /* act on key press; ignore key release */
+       if (scancode & 0x80)
+               return;
+
+       if (!sparse_keymap_report_event(dev->hotkey_dev, scancode, 1, true))
+               pr_info("Unknown key %x\n", scancode);
+}
+
 static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
 {
        acpi_status status;
+       acpi_handle ec_handle, handle;
        int error;
+       u32 hci_result;
 
        dev->hotkey_dev = input_allocate_device();
        if (!dev->hotkey_dev) {
@@ -866,21 +951,67 @@ static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        if (error)
                goto err_free_dev;
 
+       /*
+        * For some machines the SCI responsible for providing hotkey
+        * notification doesn't fire. We can trigger the notification
+        * whenever the Fn key is pressed using the NTFY method, if
+        * supported, so if it's present set up an i8042 key filter
+        * for this purpose.
+        */
+       status = AE_ERROR;
+       ec_handle = ec_get_handle();
+       if (ec_handle)
+               status = acpi_get_handle(ec_handle, "NTFY", &handle);
+
+       if (ACPI_SUCCESS(status)) {
+               INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
+
+               error = i8042_install_filter(toshiba_acpi_i8042_filter);
+               if (error) {
+                       pr_err("Error installing key filter\n");
+                       goto err_free_keymap;
+               }
+
+               dev->ntfy_supported = 1;
+       }
+
+       /*
+        * Determine hotkey query interface. Prefer using the INFO
+        * method when it is available.
+        */
+       status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
+       if (ACPI_SUCCESS(status)) {
+               dev->info_supported = 1;
+       } else {
+               hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
+               if (hci_result == HCI_SUCCESS)
+                       dev->system_event_supported = 1;
+       }
+
+       if (!dev->info_supported && !dev->system_event_supported) {
+               pr_warn("No hotkey query interface found\n");
+               goto err_remove_filter;
+       }
+
        status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
        if (ACPI_FAILURE(status)) {
                pr_info("Unable to enable hotkeys\n");
                error = -ENODEV;
-               goto err_free_keymap;
+               goto err_remove_filter;
        }
 
        error = input_register_device(dev->hotkey_dev);
        if (error) {
                pr_info("Unable to register input device\n");
-               goto err_free_keymap;
+               goto err_remove_filter;
        }
 
+       hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &hci_result);
        return 0;
 
+ err_remove_filter:
+       if (dev->ntfy_supported)
+               i8042_remove_filter(toshiba_acpi_i8042_filter);
  err_free_keymap:
        sparse_keymap_free(dev->hotkey_dev);
  err_free_dev:
@@ -895,6 +1026,11 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
 
        remove_toshiba_proc_entries(dev);
 
+       if (dev->ntfy_supported) {
+               i8042_remove_filter(toshiba_acpi_i8042_filter);
+               cancel_work_sync(&dev->hotkey_work);
+       }
+
        if (dev->hotkey_dev) {
                input_unregister_device(dev->hotkey_dev);
                sparse_keymap_free(dev->hotkey_dev);
@@ -911,6 +1047,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
        if (dev->illumination_supported)
                led_classdev_unregister(&dev->led_dev);
 
+       if (toshiba_acpi)
+               toshiba_acpi = NULL;
+
        kfree(dev);
 
        return 0;
@@ -936,12 +1075,14 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
        struct toshiba_acpi_dev *dev;
        const char *hci_method;
-       u32 hci_result;
        u32 dummy;
        bool bt_present;
        int ret = 0;
        struct backlight_properties props;
 
+       if (toshiba_acpi)
+               return -EBUSY;
+
        pr_info("Toshiba Laptop ACPI Extras version %s\n",
               TOSHIBA_ACPI_VERSION);
 
@@ -963,11 +1104,6 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 
        mutex_init(&dev->mutex);
 
-       /* enable event fifo */
-       hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
-       if (hci_result == HCI_SUCCESS)
-               dev->system_event_supported = 1;
-
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
        dev->backlight_dev = backlight_device_register("toshiba",
@@ -1024,6 +1160,8 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 
        create_toshiba_proc_entries(dev);
 
+       toshiba_acpi = dev;
+
        return 0;
 
 error:
@@ -1036,40 +1174,64 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
        struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
        u32 hci_result, value;
        int retries = 3;
+       int scancode;
 
-       if (!dev->system_event_supported || event != 0x80)
+       if (event != 0x80)
                return;
 
-       do {
-               hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
-               switch (hci_result) {
-               case HCI_SUCCESS:
-                       if (value == 0x100)
-                               continue;
-                       /* act on key press; ignore key release */
-                       if (value & 0x80)
-                               continue;
-
-                       if (!sparse_keymap_report_event(dev->hotkey_dev,
-                                                       value, 1, true)) {
-                               pr_info("Unknown key %x\n",
-                                      value);
+       if (dev->info_supported) {
+               scancode = toshiba_acpi_query_hotkey(dev);
+               if (scancode < 0)
+                       pr_err("Failed to query hotkey event\n");
+               else if (scancode != 0)
+                       toshiba_acpi_report_hotkey(dev, scancode);
+       } else if (dev->system_event_supported) {
+               do {
+                       hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
+                       switch (hci_result) {
+                       case HCI_SUCCESS:
+                               toshiba_acpi_report_hotkey(dev, (int)value);
+                               break;
+                       case HCI_NOT_SUPPORTED:
+                               /*
+                                * This is a workaround for an unresolved
+                                * issue on some machines where system events
+                                * sporadically become disabled.
+                                */
+                               hci_write1(dev, HCI_SYSTEM_EVENT, 1,
+                                          &hci_result);
+                               pr_notice("Re-enabled hotkeys\n");
+                               /* fall through */
+                       default:
+                               retries--;
+                               break;
                        }
-                       break;
-               case HCI_NOT_SUPPORTED:
-                       /* This is a workaround for an unresolved issue on
-                        * some machines where system events sporadically
-                        * become disabled. */
-                       hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
-                       pr_notice("Re-enabled hotkeys\n");
-                       /* fall through */
-               default:
-                       retries--;
-                       break;
-               }
-       } while (retries && hci_result != HCI_EMPTY);
+               } while (retries && hci_result != HCI_EMPTY);
+       }
+}
+
+static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
+                               pm_message_t state)
+{
+       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       u32 result;
+
+       if (dev->hotkey_dev)
+               hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE, &result);
+
+       return 0;
 }
 
+static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
+{
+       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       u32 result;
+
+       if (dev->hotkey_dev)
+               hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &result);
+
+       return 0;
+}
 
 static struct acpi_driver toshiba_acpi_driver = {
        .name   = "Toshiba ACPI driver",
@@ -1080,6 +1242,8 @@ static struct acpi_driver toshiba_acpi_driver = {
                .add            = toshiba_acpi_add,
                .remove         = toshiba_acpi_remove,
                .notify         = toshiba_acpi_notify,
+               .suspend        = toshiba_acpi_suspend,
+               .resume         = toshiba_acpi_resume,
        },
 };
 
@@ -1087,6 +1251,14 @@ static int __init toshiba_acpi_init(void)
 {
        int ret;
 
+       /*
+        * Machines with this WMI guid aren't supported due to bugs in
+        * their AML. This check relies on wmi initializing before
+        * toshiba_acpi to guarantee guids have been identified.
+        */
+       if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+               return -ENODEV;
+
        toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
        if (!toshiba_proc_dir) {
                pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
index e549eeeda121fb28829807899307ace2491a0e4f..41781ed8301c737018494bb30a19677640cc9018 100644 (file)
@@ -67,19 +67,8 @@ static struct platform_driver xo1_rfkill_driver = {
        .remove         = __devexit_p(xo1_rfkill_remove),
 };
 
-static int __init xo1_rfkill_init(void)
-{
-       return platform_driver_register(&xo1_rfkill_driver);
-}
-
-static void __exit xo1_rfkill_exit(void)
-{
-       platform_driver_unregister(&xo1_rfkill_driver);
-}
+module_platform_driver(xo1_rfkill_driver);
 
 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:xo1-rfkill");
-
-module_init(xo1_rfkill_init);
-module_exit(xo1_rfkill_exit);
index b859d16cf78c548462f90bf6c37f7a7c84f9266a..769d265b221b9c3abee2b8ea86a1d84ef00ac795 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/page.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "pnpbios.h"
index cfe86853feb28a3c26750777e6f0f3397561945d..9d4222648640b511e78472116e2af6e9cb46f6c3 100644 (file)
@@ -65,7 +65,6 @@
 
 #include <asm/page.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "../base.h"
index dc87eda6581434c9708173948878e906e46319f6..eb415bd7649418f1d91b5c45b98fe9411f5171d3 100644 (file)
@@ -458,6 +458,11 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
        if (rtc->uie_rtctimer.enabled == enabled)
                goto out;
 
+       if (rtc->uie_unsupported) {
+               err = -EINVAL;
+               goto out;
+       }
+
        if (enabled) {
                struct rtc_time tm;
                ktime_t now, onesec;
index f04761e6622dddcc34a3e860b7559ea410a9d113..afee0e8ae714426ad787fbe1be7d372c888e87f0 100644 (file)
@@ -376,6 +376,9 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work);
        schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL);
 #endif /* VRTC_CALIBRATION */
+
+       device_init_wakeup(&pdev->dev, 1);
+
        return 0;
 out_rtc:
        free_irq(info->irq, info);
@@ -401,10 +404,34 @@ static int __devexit pm860x_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_rtc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag |= 1 << PM8607_IRQ_RTC;
+       return 0;
+}
+static int pm860x_rtc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag &= ~(1 << PM8607_IRQ_RTC);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_rtc_pm_ops, pm860x_rtc_suspend, pm860x_rtc_resume);
+
 static struct platform_driver pm860x_rtc_driver = {
        .driver         = {
                .name   = "88pm860x-rtc",
                .owner  = THIS_MODULE,
+               .pm     = &pm860x_rtc_pm_ops,
        },
        .probe          = pm860x_rtc_probe,
        .remove         = __devexit_p(pm860x_rtc_remove),
index e954a759ba85e379fb2fd087ded474ac03ef43ee..42f5f829b3ee1c0ff8adfcc3d120f47367b7cd05 100644 (file)
@@ -360,6 +360,8 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)
                                                &mpc5200_rtc_ops, THIS_MODULE);
        }
 
+       rtc->rtc->uie_unsupported = 1;
+
        if (IS_ERR(rtc->rtc)) {
                err = PTR_ERR(rtc->rtc);
                goto out_free_irq;
index 4940fa8c4e1002f913e7f3171d8cdc72bd5310fb..50a5c4adee4807e7027fefb392bd137e63aca0f8 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/bitops.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
index 168525a9c2928b4c6a591ea9b89dc2fbaac978ac..231a1d85127b8778d8fdcac0c09662868201c739 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/chpid.h>
 #include <asm/sclp.h>
 #include <asm/setup.h>
+#include <asm/ctl_reg.h>
 
 #include "sclp.h"
 
index 425f741a280c4668ba17befa8762b4bd227fcb24..d0a2dff43fb47eaf95d5097ad42312ddf46e24c1 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <asm/crw.h>
+#include <asm/ctl_reg.h>
 
 static DEFINE_MUTEX(crw_handler_mutex);
 static crw_handler_t crw_handlers[NR_RSCS];
index 12ae1817b172380c9a13d342228c2571cacbbde9..7e9a72eb2fe0f023b6510cd1170ba0d3b36030da 100644 (file)
 #include <asm/reset.h>
 #include <asm/airq.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/isc.h>
 #include <linux/hrtimer.h>
 #include <linux/ktime.h>
+#include <asm/facility.h>
 
 #include "ap_bus.h"
 
index 826157f386943940367f663b20415e2c01fc571f..327657e2e2648ca79b8030e1c1218972076f8e90 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
index 8d6e508222b84529744e97c2906a084d0ee3375a..2236aea3ca2fde226e1e85fcffd3461f2321d06c 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/fs.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/openpromio.h>
 #ifdef CONFIG_PCI
index 0b31658ccde5cd8be14d3b1f54a06670c1c375df..a9e468cc1caca686f82459341fcaa13f71addbeb 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index f672491774eb61756c2a36f8af3a36496a7ea53c..a3adfb4357f54fab69a12fad742e18213328cb50 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/byteorder.h>
index f66c33b9ab41ac7333d99f3f3423ce497e47ae1d..d4da3708763b7612ef5e7574578245c5e4534c1f 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index bfd618a6949956f70e41ecd9a910f8422c7a02bb..374c4edf4fcbc2a62f82d30e0b38bb2313a471ab 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/firmware.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 
 #include <scsi/scsi_cmnd.h>
index f17c92cf808b1fafa4e4cd7d13e8ad3eed6d89c6..19a36945e6fdaca44aba5ab076d1d3171410a6bf 100644 (file)
 #include <asm/irq.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
-#include <asm/system.h>
 #include <linux/completion.h>
 #include <linux/errno.h>
 #include <linux/string.h>
index ed119cedaae008354128e6a2cbe9fc129ad736b2..ede91f3780000699360e3d0c6361b22d49968c54 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/slab.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
index 1c10b796c1a25c3153a978555025a749af026979..a3e6ed353917f9018f2613db4095101199eb6fae 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/gfp.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
index 2fe9e90e53d9fdbf4fafcbd08dde781bdc6b197e..cbde1dca45ad52e37eede57572f19b825cd39408 100644 (file)
@@ -61,7 +61,6 @@
 #include <linux/aer.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi.h>
index c454e44cf51c6653b8fd050c681ba64eea719b63..b330438ac662631bdc720426fdb7cad5a539cd4c 100644 (file)
 #include <linux/stringify.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/ecard.h>
 
 #include "../scsi.h"
index a3398fe70a9c5f8d0214869f7bf8f921d30b07cd..c3b99c93637aaa1ec958fe0dde1c2b9998226ccb 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/ecard.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "../scsi.h"
 #include <scsi/scsi_host.h>
index 849cdf89f7bbdcada963da8678d4b6a5291a4ea5..d25f944b59c27a42e1c034a3e85b75a68326f5e9 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/ecard.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "../scsi.h"
 #include <scsi/scsi_host.h>
index 7e6eca4a125e91f75c55280dbbc34ee3d03a9010..f29d5121d5ed2985af146a6416b0618293246cd8 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/blkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
index c2677ba29c74619ad581b895018ffd07ee3ce9b5..4b11bb04f5c46c51574bcbae994184f3ce19060c 100644 (file)
@@ -72,7 +72,6 @@
 #endif
 
 
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/blkdev.h>
index a2c6135d337edab43838a94ee9c9ffc1061b216a..53bfcaa86f09c71365697d094e3e2391d2f29caf 100644 (file)
@@ -93,7 +93,6 @@
 #include <linux/mca-legacy.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
index 643f6d500fe7ec409818a01c09a19fcc4e7f3fc7..1a2a1e5824e3a5f117adba1661a4c9cbd2ce32f6 100644 (file)
 #include <linux/slab.h>
 #include <scsi/scsicam.h>
 
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index 81182badfeb10f62c5e499c8d587198ac37fa696..1a5954f0915acc3739e18115dea344a6f2b080ca 100644 (file)
 #undef NCR5380_STAT_LIMIT
 #endif
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/signal.h>
 #include <linux/blkdev.h>
index d42ec921de46e6215be8b1f76ef539638982d1fb..5d72274c507ff7d271b607289dcced6e0f6c3138 100644 (file)
 #include <linux/reboot.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
index 67fc8ffd52e68eeb2bfe311d04d6bc2052895f74..cd09132d5d7d22eb7c2d240b0d2da6758ad837a3 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
index bdfa223a7dbb9e047c278b6414c5135e49a47001..134a0ae85bb7d8d996252879b8dfb5b413f4ac0f 100644 (file)
@@ -4890,11 +4890,8 @@ static struct vio_driver ibmvfc_driver = {
        .probe = ibmvfc_probe,
        .remove = ibmvfc_remove,
        .get_desired_dma = ibmvfc_get_desired_dma,
-       .driver = {
-               .name = IBMVFC_NAME,
-               .owner = THIS_MODULE,
-               .pm = &ibmvfc_pm_ops,
-       }
+       .name = IBMVFC_NAME,
+       .pm = &ibmvfc_pm_ops,
 };
 
 static struct fc_function_template ibmvfc_transport_functions = {
index e984951baeb6834b27d82b26f5afa6dbcc0bf471..3a6c4742951ea4f1e661c4973a48fdd16abb501d 100644 (file)
@@ -2061,11 +2061,8 @@ static struct vio_driver ibmvscsi_driver = {
        .probe = ibmvscsi_probe,
        .remove = ibmvscsi_remove,
        .get_desired_dma = ibmvscsi_get_desired_dma,
-       .driver = {
-               .name = "ibmvscsi",
-               .owner = THIS_MODULE,
-               .pm = &ibmvscsi_pm_ops,
-       }
+       .name = "ibmvscsi",
+       .pm = &ibmvscsi_pm_ops,
 };
 
 static struct srp_function_template ibmvscsi_transport_functions = {
index 2256babe047463fa04621efcf432b0affe80ff71..aa7ed81e92371140738bbe4f8d32559662e9b3d7 100644 (file)
@@ -918,10 +918,7 @@ static struct vio_driver ibmvstgt_driver = {
        .id_table = ibmvstgt_device_table,
        .probe = ibmvstgt_probe,
        .remove = ibmvstgt_remove,
-       .driver = {
-               .name = "ibmvscsis",
-               .owner = THIS_MODULE,
-       }
+       .name = "ibmvscsis",
 };
 
 static int get_system_info(void)
index 112f1bec7756d4ac2da9ed16790a746d8104a110..deb5b6d8398ec2a1a2dfc90f7df31e8046d7ff33 100644 (file)
 #include <linux/stat.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
index e6173376605d4d9f52bb01727f6d078f3da26ab9..e5cd8d8d4ce7d4639a0e762603c6401ede3e6291 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pci-bridge.h>
 #include <asm/macio.h>
 
index 2bccfbe5661e652bc24736cc572004698a7aecca..24828b54773a627a2c866d008cabfbc06aa3b534 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <asm/macintosh.h>
 #include <asm/macints.h>
index 494474779532b697cb0667b8d1c5ded052fb0ef3..e8a04ae3276a703a64d1c33d987624ef13d4e42a 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/hydra.h>
 #include <asm/processor.h>
index 4b3b4755945c81565991f64265b18062d92cbc18..5982a587babc875a56aaba6ed9983860c8b593a9 100644 (file)
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index 002924963cd89aa0af5e4588ae2827aefed95b2b..62b616891a33f684f0081a6efa427d4a6a22f3d1 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
index de0b1a704fb508d95fb6f7874bbe1433dcb92f4c..21883a2d6324b19202446bb1d7107d59ed2908aa 100644 (file)
@@ -54,7 +54,6 @@ static const char * osst_version = "0.99.4";
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 /* The driver prints some debugging information on the console if DEBUG
    is defined and non-zero. */
index f2018b46f4948950ee310cc15b70b55205e00cbd..2f72c9807b12181684d1e84fa40998281c4e3523 100644 (file)
  
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/proc_fs.h>
 #include <asm/io.h>
index d838205ab1691c7290e5f9f65f77b7d0bd86c9db..6c6486f626ee6e823725faa5cc21a7452a3ccad7 100644 (file)
 #include <asm/byteorder.h>
 #include <asm/processor.h>
 #include <asm/types.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index e40dc1cb09a0bdd89606981fe341cdd4630edbd5..b191dd549207db3ac2c25fd16e3b6a87559cb047 100644 (file)
@@ -35,7 +35,6 @@
 #include "qlogicpti.h"
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
index 9262cdfa4b232f8fd33a03d523db87a77e3cfa8e..a15f691f9d3423e270f17b1267e81ba1b105f252 100644 (file)
@@ -42,7 +42,6 @@ static const char *verstr = "20101219";
 
 #include <asm/uaccess.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
index baf7328de95681d6d71db2aeb9a13b7265646518..6e25889db9d4512cdf89403bb09b55d8405c97b4 100644 (file)
@@ -63,7 +63,6 @@
 #include <linux/blkdev.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/sun3ints.h>
 #include <asm/dvma.h>
index fbba78e5722e604f09555c0ae713c5db3afb8c5d..a3dd55d1d2fdb3d3a4294707614ef033f9d9831b 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/blkdev.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/sun3ints.h>
 #include <asm/dvma.h>
index 012c86edd59f950cedcd2284a26d0b49d153f036..ac4eca6a532810d71de3812cf377847d484bc388 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/blkdev.h>
 #include <linux/isapnp.h>
index 041eaaace2c308a42ce1c6abba9b8dd89992b3a7..d672d97fb84adcee58886164c72579615ac65c10 100644 (file)
  * $Log: t128.c,v $
  */
 
-#include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
index 90e104d6b55826caece982dc310500bc756ae7f7..9c216e5635685f109eb9c68c41c56a062b483220 100644 (file)
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
index 7e22b737dfd8ff4216f4eeddd015066b08ca2e0c..14e0c40a68c93928fda99e7323bc8f8fd89a58fc 100644 (file)
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 
 #define ULTRASTOR_PRIVATE      /* Get the private stuff from ultrastor.h */
index 9ee0afef2d161f1c63d1ffdef321e33794b041aa..d89a5dfd3adec9463061651a23cf0d486489f02b 100644 (file)
 #include <linux/stat.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 
 #include <scsi/scsi.h>
index cec7a96f2c098f632d3a50865b7cece306007f92..bc780807ccb0febf460bc5de45517a8c26b82bd2 100644 (file)
@@ -9,7 +9,7 @@
  */
 #include "internals.h"
 
-static unsigned long dist_handle[NR_IRQS];
+static unsigned long dist_handle[INTC_NR_IRQS];
 
 void intc_balancing_enable(unsigned int irq)
 {
index e53e449b4ecab0b83ab6fe110cb0df4ff8dff963..2fde8970dfd0716dda4fcf69395da9be7bf80214 100644 (file)
@@ -42,7 +42,7 @@ unsigned int nr_intc_controllers;
  * - this needs to be at least 2 for 5-bit priorities on 7780
  */
 static unsigned int default_prio_level = 2;    /* 2 - 16 */
-static unsigned int intc_prio_level[NR_IRQS];  /* for now */
+static unsigned int intc_prio_level[INTC_NR_IRQS];     /* for now */
 
 unsigned int intc_get_dfl_prio_level(void)
 {
index 057ce56829bf37b1c57093eb0734ed80b2dad36a..f461d5300b81d77fcc06915669c3eb9b56ea8e91 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/spinlock.h>
 #include "internals.h"
 
-static unsigned long ack_handle[NR_IRQS];
+static unsigned long ack_handle[INTC_NR_IRQS];
 
 static intc_enum __init intc_grp_id(struct intc_desc *desc,
                                    intc_enum enum_id)
index c7ec49ffd9f63806a73b14e39ec6bbedbf6de8cf..93cec21e788bdb7b4024fa5237b9d7a8801c1333 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/export.h>
 #include "internals.h"
 
-static struct intc_map_entry intc_irq_xlate[NR_IRQS];
+static struct intc_map_entry intc_irq_xlate[INTC_NR_IRQS];
 
 struct intc_virq_list {
        unsigned int irq;
index 8418eb03665121db4a6caf809ea8efc4f12b170c..b9f0192758d6d929aab86d087c443adc46154e66 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
+#include <linux/types.h>
 
 #include "spi-dw.h"
 
@@ -136,6 +137,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        txconf.dst_maxburst = LNW_DMA_MSIZE_16;
        txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+       txconf.device_fc = false;
 
        txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
                                       (unsigned long) &txconf);
@@ -144,7 +146,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        dws->tx_sgl.dma_address = dws->tx_dma;
        dws->tx_sgl.length = dws->len;
 
-       txdesc = txchan->device->device_prep_slave_sg(txchan,
+       txdesc = dmaengine_prep_slave_sg(txchan,
                                &dws->tx_sgl,
                                1,
                                DMA_MEM_TO_DEV,
@@ -158,6 +160,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        rxconf.src_maxburst = LNW_DMA_MSIZE_16;
        rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+       rxconf.device_fc = false;
 
        rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
                                       (unsigned long) &rxconf);
@@ -166,7 +169,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
        dws->rx_sgl.dma_address = dws->rx_dma;
        dws->rx_sgl.length = dws->len;
 
-       rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+       rxdesc = dmaengine_prep_slave_sg(rxchan,
                                &dws->rx_sgl,
                                1,
                                DMA_DEV_TO_MEM,
index d46e55c720b7f71717d5772b034c5b7f3e159dc4..6db2887852d6befe327b53cacdf2731b8328c68b 100644 (file)
@@ -633,8 +633,8 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
        if (!nents)
                return ERR_PTR(-ENOMEM);
 
-       txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
-                                                slave_dirn, DMA_CTRL_ACK);
+       txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents,
+                                       slave_dirn, DMA_CTRL_ACK);
        if (!txd) {
                dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
                return ERR_PTR(-ENOMEM);
index 610f7391456eadaaa33cd3f610a2e0503cbeb527..9b0d716960394a21c69f22ea74a1ed33958de62e 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/spi/spi_bitbang.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/io.h>
index dc8485d1e883adfa10fcded8710c2a8007ba991a..96f0da66b185b5cbb41c6cdf01d7e969e5b341ed 100644 (file)
@@ -880,10 +880,12 @@ static int configure_dma(struct pl022 *pl022)
        struct dma_slave_config rx_conf = {
                .src_addr = SSP_DR(pl022->phybase),
                .direction = DMA_DEV_TO_MEM,
+               .device_fc = false,
        };
        struct dma_slave_config tx_conf = {
                .dst_addr = SSP_DR(pl022->phybase),
                .direction = DMA_MEM_TO_DEV,
+               .device_fc = false,
        };
        unsigned int pages;
        int ret;
@@ -1017,7 +1019,7 @@ static int configure_dma(struct pl022 *pl022)
                goto err_tx_sgmap;
 
        /* Send both scatterlists */
-       rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+       rxdesc = dmaengine_prep_slave_sg(rxchan,
                                      pl022->sgt_rx.sgl,
                                      rx_sglen,
                                      DMA_DEV_TO_MEM,
@@ -1025,7 +1027,7 @@ static int configure_dma(struct pl022 *pl022)
        if (!rxdesc)
                goto err_rxdesc;
 
-       txdesc = txchan->device->device_prep_slave_sg(txchan,
+       txdesc = dmaengine_prep_slave_sg(txchan,
                                      pl022->sgt_tx.sgl,
                                      tx_sglen,
                                      DMA_MEM_TO_DEV,
index 5c6fa5ed3366fef69b7cef2b8b49ce67a0620935..ec47d3bdfd13233b68774e59fedf6b77570c3c16 100644 (file)
@@ -1099,7 +1099,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
                sg_dma_address(sg) = dma->rx_buf_dma + sg->offset;
        }
        sg = dma->sg_rx_p;
-       desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg,
+       desc_rx = dmaengine_prep_slave_sg(dma->chan_rx, sg,
                                        num, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc_rx) {
@@ -1158,7 +1158,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
                sg_dma_address(sg) = dma->tx_buf_dma + sg->offset;
        }
        sg = dma->sg_tx_p;
-       desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx,
+       desc_tx = dmaengine_prep_slave_sg(dma->chan_tx,
                                        sg, num, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc_tx) {
index 59e095362c81cd1ddfed2d5087bc5048a09a2b15..c2832124bb3e7ade105ef66d82471d2d509d2110 100644 (file)
@@ -381,8 +381,7 @@ int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
 
 repeat:
        fdt = files_fdtable(files);
-       fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
-                               files->next_fd);
+       fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, files->next_fd);
 
        /*
         * N.B. For clone tasks sharing a files structure, this test
@@ -410,11 +409,11 @@ repeat:
                goto repeat;
        }
 
-       FD_SET(fd, fdt->open_fds);
+       __set_open_fd(fd, fdt);
        if (flags & O_CLOEXEC)
-               FD_SET(fd, fdt->close_on_exec);
+               __set_close_on_exec(fd, fdt);
        else
-               FD_CLR(fd, fdt->close_on_exec);
+               __clear_close_on_exec(fd, fdt);
        files->next_fd = fd + 1;
 #if 1
        /* Sanity check */
@@ -455,7 +454,7 @@ static void task_fd_install(
 static void __put_unused_fd(struct files_struct *files, unsigned int fd)
 {
        struct fdtable *fdt = files_fdtable(files);
-       __FD_CLR(fd, fdt->open_fds);
+       __clear_open_fd(fd, fdt);
        if (fd < files->next_fd)
                files->next_fd = fd;
 }
@@ -481,7 +480,7 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd)
        if (!filp)
                goto out_unlock;
        rcu_assign_pointer(fdt->fd[fd], NULL);
-       FD_CLR(fd, fdt->close_on_exec);
+       __clear_close_on_exec(fd, fdt);
        __put_unused_fd(files, fd);
        spin_unlock(&files->file_lock);
        retval = filp_close(filp, files);
index db1fd63aaab383a14c10fd70af15195f98f5a820..bf185e2807d1d616a06068499785268ef934b9cf 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include "comedidev.h"
 #include "internal.h"
index c9e8c4785768ce35f68edb264b4c1489c8f15e16..915157d47805562ef039c683d2279c185a786bc7 100644 (file)
@@ -86,7 +86,6 @@ TODO:
 #include "../comedidev.h"
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 
 #include "comedi_pci.h"
 #include "8253.h"
index fd274e9c7b78b85662867823c90aba670d09ac1a..13e9c80716968df8b2bc9df3a46c7ee54f983104 100644 (file)
@@ -55,7 +55,6 @@
 #include "comedi_pci.h"
 #include "../comedidev.h"
 
-#include <asm/system.h>
 
 #define PCI_MITE_SIZE          4096
 #define PCI_DAQ_SIZE           4096
index 8cd51a7aad8ec7e0f6e8c4693fc846e7d7f37ab8..647e116e10deefc7fd4ea6e7ac87c986b53c78f8 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef _BC_DTS_DEFS_H_
 #define _BC_DTS_DEFS_H_
 
+#include <linux/types.h>
+
 /* BIT Mask */
 #define BC_BIT(_x)             (1 << (_x))
 
index 3f4d79515026b06a4ec6b264f4f7a06f5fb1db9b..b3a550bd5b060690ee17fe4629e32d39149375b0 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _CRYSTALHD_H_
 #define _CRYSTALHD_H_
 
-#include <asm/system.h>
 #include "bc_dts_defs.h"
 #include "crystalhd_misc.h"
 #include "bc_dts_glob_lnx.h"
index a81f9298b0a18b47c3361382a07fab435cc14c47..a9e36336d097b5d8ae8850d58ec199c43f7b4dbf 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include "crystalhd.h"
index 84c87938a8319507243105753874da9ffe7c2d83..8cdaa7a3481460834ab541126d657ce9814318bc 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/ioctl.h>
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
+#include "bc_dts_glob_lnx.h"
 
 /* Global log level variable defined in crystal_misc.c file */
 extern uint32_t g_linklog_level;
index 3f919babe79bbf9ce8e54b5db39f3c9a7de68cf5..886f5650444e917281508d679aed5a32d26d6aa8 100644 (file)
@@ -70,7 +70,6 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 7569aa0f24d152bc527136ec7a4a42b7fd5f2f45..c4a8a0a26eb5bbe18920a2ff1f5338630b8cf634 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
index 6c9279a6d60657301f7af1c8142bca9639006667..ece2dd146487b5051bb22e82560b2b871750fe8d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <linux/videodev2.h>
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
index b8cfa1a6eaeb8983bbf555195654df45543a3784..6bc82aaeef110e3135850daed2c6aca4b4f8302f 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include "go7007-priv.h"
 #include "wis-i2c.h"
index f91658670e34f2de766575e1b97a9901f2c50258..3ef4cd8b4de38b992387ee4866d5a3ddce04ba8b 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include "go7007.h"
 #include "go7007-priv.h"
index d071c838ac2a3b7ce1fff2574fca926dcadcdea7..5af29ff68bfd6d2b5504222fb9d5dcd143fb77c2 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
index 97352cf6bd9886d334714f9e01c072c2ebea74a5..3295ea63f3eb5d53bcafabc39a372846ba0610b3 100644 (file)
@@ -66,7 +66,6 @@
 #include <linux/poll.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/fcntl.h>
index c94382b917aca0b49057b8c3b57ad0e1166b327f..945d9623550b621c2731091a7804c66e3949e25e 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
-#include <asm/system.h>
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <linux/fcntl.h>
index a6910da78a64232af3d88872310074af1f8645b1..cf4c29d10e7f588cbb404afa2daa06aaf7757f13 100644 (file)
@@ -323,6 +323,7 @@ static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int t
        mutex_lock(&dev->device_lock);
 
        dev->wd_timeout = timeout;
+       wd_dev->timeout = timeout;
        mei_wd_set_start_timeout(dev, dev->wd_timeout);
 
        mutex_unlock(&dev->device_lock);
index 4683d5f355c01f0d3860bd0a83a1a4d6e64ac29b..6183573f112f3487ac0caf0add169c521115f4b5 100644 (file)
@@ -58,7 +58,6 @@
 
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #define LCD_MINOR              156
 #define KEYPAD_MINOR           185
index b458ff034067edb46da0bc89e4f789069726fce8..9a50bcc59594c50eebca92b3bfa822bf774b9070 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/ip.h>
-#include <asm/system.h>
 #include "2t3e3.h"
 #include "ctrl.h"
 
index 1915af2011757d581cee0e163052fd4b94c35e45..1dd0b6717ccc5b0a549950789e9b7dad509455da 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/phonedev.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/kmod.h>
 #include <linux/sem.h>
index a2f31c69d12e89dbe746d062e54ed4ddaf45e681..ed00d3da3205a0074333fb0a4dfd778ca6417280 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef _HOST_OS_H_
 #define _HOST_OS_H_
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
index a2cbb29c3f597e0ce01c79115778f0e5be8edd56..7084f414846e946e1d557f322a8da87f738b36c2 100644 (file)
@@ -74,7 +74,6 @@
 #include <linux/in.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
index dab603e0f452ce583804a3eb13e8a32e68b38086..d5bf0a7012f2f4f8dc8bc96e97ef14f5d8a564c4 100644 (file)
@@ -86,8 +86,7 @@
 // #include <linux/in.h>
 // #include <linux/delay.h>
 // #include <asm/io.h>
-// #include <asm/system.h>
-// #include <asm/bitops.h>
+// // #include <asm/bitops.h>
 #include <linux/unistd.h>
 #include <asm/uaccess.h>
 
index 9c16f5478a75b04678b7e7ba7da9ea0000973259..90820ff1aced92bf14a0ecd4944583cfba024d6a 100644 (file)
@@ -79,8 +79,7 @@
 // #include <linux/delay.h>
 // #include <linux/skbuff.h>
 // #include <asm/io.h>
-// #include <asm/system.h>
-// #include <asm/bitops.h>
+// // #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
index 2bd9b84ace8e2e56b057782046ba5272effecb15..3df990c7306abe116936c08528e561ccb0e858de 100644 (file)
@@ -77,7 +77,6 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/delay.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
index b748a3ff7954b57ff3f93deed92a8e53d0e997ae..f104e6f1e980be07a974abaacdba66d9655e0c69 100644 (file)
@@ -73,8 +73,7 @@
 // #include <linux/in.h>
 // #include <linux/delay.h>
 // #include <asm/io.h>
-// #include <asm/system.h>
-// #include <asm/bitops.h>
+// // #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index afadcd43d14ee53f77f07c5d52e90842aa857cc9..24145c30c9b069104564df2f9e14b19f8728740b 100644 (file)
@@ -85,7 +85,6 @@ static char *serial_version = "4.30";
 
 #include <asm/setup.h>
 
-#include <asm/system.h>
 
 #include <asm/irq.h>
 
index 3a0d53d6368f2f177afc3fc7528ec27cdbd56027..ee307799271a4d3cd362cb131a58490d0d00f18b 100644 (file)
@@ -310,11 +310,8 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev)
 static struct vio_driver hvc_vio_driver = {
        .id_table       = hvc_driver_table,
        .probe          = hvc_vio_probe,
-       .remove         = __devexit_p(hvc_vio_remove),
-       .driver         = {
-               .name   = hvc_driver_name,
-               .owner  = THIS_MODULE,
-       }
+       .remove         = hvc_vio_remove,
+       .name           = hvc_driver_name,
 };
 
 static int __init hvc_vio_init(void)
index d23759183b4782485f03db20de7fa57279a41ca7..3436436fe2d7bc7317e8b43cae2dadfd4cad5f72 100644 (file)
@@ -879,10 +879,7 @@ static struct vio_driver hvcs_vio_driver = {
        .id_table       = hvcs_driver_table,
        .probe          = hvcs_probe,
        .remove         = __devexit_p(hvcs_remove),
-       .driver         = {
-               .name   = hvcs_driver_name,
-               .owner  = THIS_MODULE,
-       }
+       .name           = hvcs_driver_name,
 };
 
 /* Only called from hvcs_get_pi please */
index 03c14979accf49f68103c00df3763a28a4598eda..794ecb40017ce2257a0b5babac7262ae52c43ed1 100644 (file)
 
 #include <linux/uaccess.h>
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include <linux/pci.h>
 
index 8a8d0440bab0c44f82d3576b901d7260b234a54b..324467d28a5497bcca18b2f52d31943d2747f795 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 17ff377e41292899dc9c8eac0f7a2941a377d616..c6f372dd5623c7b077047ce2023f2da9c9e0461d 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index a09ce3ef5d748f9455ebba56b38aa97f097e8187..1b2db9a3038c3b49bb7237d92d3fed7ddecdbef4 100644 (file)
 #include <linux/if.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/termios.h>
 #include <asm/uaccess.h>
 
index d2256d08ee7e11995a0e5e5067d5a4c1b73b4de7..94b6eda87afdd8a7a5ac761eddd04a9b618d77bd 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 
 /* number of characters left in xmit buffer before select has we have room */
 #define WAKEUP_CHARS 256
index f96ecaec24f81f9157809f173e8184dcde352c99..eeae7fafe9a7de2f8d7d33a404608b445b6ecc9b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/devpts_fs.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 
 #ifdef CONFIG_UNIX98_PTYS
 static struct tty_driver *ptm_driver;
index f899996b4363d2a7d3ff829856b441bb9bf465fc..a44345a2dbb47622e0f7370f77e61f17b7351ece 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
+#include <asm/system_info.h>
 #include <asm/hardware/dec21285.h>
 #include <mach/hardware.h>
 
index 7398390e7e65111b0658a52e1559045651e42363..5ce782529d65c5713551b80a0e2fc8572a45c2b9 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 
index 86090605a84ee52291234c882470f67db012df4b..29b695d041ecd45cdfe18914b8c02d10ff7f79a5 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
index 20d795d9b59104329d96ddf9e113877cf693b0a7..0c65c9e669867bf70ed3c86e61e06b3846bf5b60 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/delay.h>
+#include <linux/types.h>
 
 #include <asm/io.h>
 #include <asm/sizes.h>
@@ -271,6 +272,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
                .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
                .direction = DMA_MEM_TO_DEV,
                .dst_maxburst = uap->fifosize >> 1,
+               .device_fc = false,
        };
        struct dma_chan *chan;
        dma_cap_mask_t mask;
@@ -304,6 +306,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
                        .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
                        .direction = DMA_DEV_TO_MEM,
                        .src_maxburst = uap->fifosize >> 1,
+                       .device_fc = false,
                };
 
                chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
@@ -481,7 +484,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
                return -EBUSY;
        }
 
-       desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV,
+       desc = dmaengine_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV,
                                             DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
@@ -664,7 +667,6 @@ static void pl011_dma_rx_callback(void *data);
 static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
 {
        struct dma_chan *rxchan = uap->dmarx.chan;
-       struct dma_device *dma_dev;
        struct pl011_dmarx_data *dmarx = &uap->dmarx;
        struct dma_async_tx_descriptor *desc;
        struct pl011_sgbuf *sgbuf;
@@ -675,8 +677,7 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
        /* Start the RX DMA job */
        sgbuf = uap->dmarx.use_buf_b ?
                &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
-       dma_dev = rxchan->device;
-       desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1,
+       desc = dmaengine_prep_slave_sg(rxchan, &sgbuf->sg, 1,
                                        DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        /*
index 23d7916968793652e61a050531d2bae00bcecfd5..5b07c0c3a10c2f7ac39fcae84c4581f16c8baa99 100644 (file)
@@ -34,9 +34,9 @@ static char *serial_version = "$Revision: 1.25 $";
 
 #include <asm/irq.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 #include <arch/svinto.h>
+#include <arch/system.h>
 
 /* non-arch dependent serial structures are in linux/serial.h */
 #include <linux/serial.h>
index e3699a84049f1c1eb26c7f66cca2c21278cd24fa..6491b8644a7f2e84730082f37041207989764b71 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/atomic.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/kn01.h>
index d55709a7a75a1ca4629ea2ffb9b705620dd6bf71..defc4e3393a38accf1664399bfbf9c7f24771a70 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/firmware.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index 5e85e1e14c44009f80ea2ae8e668b2840efc770d..fca13dc73e2302e19aee0e8773b6fa93a004a7c8 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <linux/atomic.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <mach/hardware.h>
 #include <mach/dma.h>
index 332f2eb8abbc9552e2779de0692cf6d88b05fa49..e825460478befc40ad9e9a4d36243fa741a48cf0 100644 (file)
@@ -844,7 +844,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
 
        sg_dma_address(sg) = priv->rx_buf_dma;
 
-       desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
+       desc = dmaengine_prep_slave_sg(priv->chan_rx,
                        sg, 1, DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
@@ -1003,7 +1003,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
                        sg_dma_len(sg) = size;
        }
 
-       desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
+       desc = dmaengine_prep_slave_sg(priv->chan_tx,
                                        priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
index 61b7fd2729cdd5af934766e5ec5b04d154841f25..f8db8a70c14eaaa78f6c9571b346de456c619bc8 100644 (file)
@@ -1338,7 +1338,7 @@ static void sci_submit_rx(struct sci_port *s)
                struct scatterlist *sg = &s->sg_rx[i];
                struct dma_async_tx_descriptor *desc;
 
-               desc = chan->device->device_prep_slave_sg(chan,
+               desc = dmaengine_prep_slave_sg(chan,
                        sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
 
                if (desc) {
@@ -1453,7 +1453,7 @@ static void work_fn_tx(struct work_struct *work)
 
        BUG_ON(!sg_dma_len(sg));
 
-       desc = chan->device->device_prep_slave_sg(chan,
+       desc = dmaengine_prep_slave_sg(chan,
                        sg, s->sg_len_tx, DMA_MEM_TO_DEV,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
index 3ba5d285c2d0ae805fc99deb30c48ccbbb6ae405..505961cfd93474a5b6079e0c406bfcb7c97f3815 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/spitfire.h>
 #include <asm/prom.h>
 #include <asm/irq.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index 62dacd0ba5266f49d71381db97708ebdcc1585e7..f0d93eb7e6ec51fc678d5be42542f35cb77cb741 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index d3ca6da129fe1740a070923baf06af5fd8e6effd..675303b8ed84688327d67905be2d4fe671f15fa2 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index da4415842a43f3fa472a55a5e9927b0a5666eae8..b3b70b0bf85bc8abaa36dedf44c97eb5e39080a9 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index b7455b5260800ff8873ff8597215fffb7b3454b3..4001eee6c08de214f596e932c7fe454dc0f4c2f8 100644 (file)
@@ -67,7 +67,6 @@
 #include <linux/types.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic_addrs.h>
index 8e518da85fd55749a5160de4640e9449568addbb..593d40ad0a6be9b0de161803aa69c9011e2fdab8 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/ioctl.h>
 #include <linux/synclink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index 34b1a3c43066a45b7f22153d9ad674f43215bc2c..aa1debf97cc741e3f5914cb5396c8397bd37f362 100644 (file)
@@ -73,7 +73,6 @@
 #include <linux/hdlc.h>
 #include <linux/synclink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index 4fb6c4b31b79a307638545c2b28d8dc1992f3478..a3dddc12d2fedc3ec261c2c8f2b3da215f564a20 100644 (file)
@@ -58,7 +58,6 @@
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index dd8a938510caa147719200e9aea43fff14426d93..d939bd705c71d82e6cc83af0ca05d0d3421beeda 100644 (file)
@@ -97,7 +97,6 @@
 #include <linux/ratelimit.h>
 
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/kbd_kern.h>
 #include <linux/vt_kern.h>
index 9314d93c1a20ab8b057670f56ee55bca23d66e44..a1b9a2f68567e2755871280c555f8a4f52168eb6 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #undef TTY_DEBUG_WAIT_UNTIL_SENT
 
index 84c4a7d5603efdba7095dd3986bcdcbb2da1967f..3bdd4b19dd06b6c90dd6cea689f3a31bb54454c4 100644 (file)
@@ -99,7 +99,6 @@
 #include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/kdb.h>
 #include <linux/ctype.h>
index 2204a4c68d85d04567fdea74c719d51041e70b02..77779271f4872f4d99e50bc05baa7506dea7cc11 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 /* gadget stack */
index 36fd2b4b49a2cc23e8f9d1e76fee72cc7e8c693c..0c935d7c65bdf7379f466e5c3f1522fb88a7e266 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/gpio.h>
 
 #include <mach/board.h>
index e1cd56c5e2a86b6ce58ff485dc19b5d80593464f..a6dfd21641661c08df7a524850ee6ccf670a4f3e 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/byteorder.h>
 #include <linux/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #define DRIVER_DESC    "USB Host+Gadget Emulator"
index b30e21fdbb1bd0db7800b5789909839495073946..5f94e79cd6b9b3f8856dad2d97d1e74677f62bad 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/dma.h>
 
index e1dfd32dc805d5c1e256f27ecceca13617b7358a..e151d6b87dee09966427e838db114119012cb66a 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 
index edd52d963f14ff4990ff0f3869f6f7aa6ba36326..f9cedd52cf200b375d486e06fe2c6107db8c5714 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/pm.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "langwell_udc.h"
index 19bbe80c2f8c4dda8d80d48c075643361351bee6..a73cf406e2a45c34f5b2d2ac955aaebccd1a1abf 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/platform_data/mv_usb.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "mv_udc.h"
index 01ae56f471742e0c46e10e5d315ac11fc4f0f308..43ac7482fa9184dbd4748d42d6a6008e21f330ef 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/usb/gadget.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "net2272.h"
index a5ccabc37f30049c88e06d7cfd192735c17ca88a..ac335af154ba7fa45368378a9960e4bec616e148 100644 (file)
@@ -59,7 +59,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 
index b44830df593efe1f2b45129dc011809bf9c7c8ad..3b4b6dd0f95a9a2a473a31fdb72cf8921cc64a2c 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/mach-types.h>
 
index d83134b0f78a03ff7ed2c429be95735fb88da68f..4e4dc1f5f388d7c68f274cc8040fb849f6ef3494 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/byteorder.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 1b33634f2736b132e835a35de658e8478bb45ea3..41ed69c96d8c512eab7cd50ea7a9c6d8f5cd25bf 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/byteorder.h>
 #include <asm/dma.h>
 #include <asm/gpio.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 
index d3cdffea9c8a33e71dd8fb5bacaf41c7aaf240cd..73a934a170d1a8ae891f873fb24eab383697407a 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 
index ab9c65e2c1d57c880c976b1757f58567ac3529eb..195524cde6c3d93069286c96ad7f80912ee53611 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <mach/irqs.h>
 
index aede6374e4b6bb9a12d32ea674ab5461b0210532..057cdda7a48978999ebf5ac4cbb8ecee7acc60e0 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #if defined(CONFIG_PPC_PS3)
index 924880087a747f571f06db9b23067649e8174861..9e65e3091c8a12b5bd2bde3fd063f55e8df83508 100644 (file)
@@ -70,7 +70,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "isp116x.h"
index 9e63cdf1ab753e228fb8239fc299626b09221ae1..2ed112d3e1595d45c5d6a8ab4053c883310124d1 100644 (file)
@@ -84,7 +84,6 @@
 #include <linux/prefetch.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
index 543e90e336b85f16d3e544fba1251820d7f43b5e..235171f29460574c75030b01b1f45d64dba4d069 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 
index 015c7c62ed49eb4879257e1bb393dce079c59e81..3b38030b02a87a2407f7439b7c0b8fc259fbc880 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include <linux/irq.h>
index 2a2cce2d2fa706b6ab59a562295fb4e6ec7666a0..91ce1c02e6173d78564562afb71f005b3af4af65 100644 (file)
@@ -51,7 +51,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
index 16dd6a6abf007ced8c0be9204350a865318c50e8..dbbd1ba2522412ef7e1f28c6e83e942f5ac14ffc 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
        /* FIXME ohci.h is ONLY for internal use by the OHCI driver.
index e37dea87bb5633fe8d88b77f443edb761f1aa584..e4db350602b8ea639aca1a1d30a069901f0e4db8 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "uhci-hcd.h"
 
index 97cb45916c4351110e3a21fb2613c2954855ee9b..d05c7fbbb7030a3981eff9cb3ce8b5f5d83c3cc6 100644 (file)
@@ -115,12 +115,12 @@ static bool ux500_configure_channel(struct dma_channel *channel,
        slave_conf.dst_addr = usb_fifo_addr;
        slave_conf.dst_addr_width = addr_width;
        slave_conf.dst_maxburst = 16;
+       slave_conf.device_fc = false;
 
        dma_chan->device->device_control(dma_chan, DMA_SLAVE_CONFIG,
                                             (unsigned long) &slave_conf);
 
-       dma_desc = dma_chan->device->
-                       device_prep_slave_sg(dma_chan, &sg, 1, direction,
+       dma_desc = dmaengine_prep_slave_sg(dma_chan, &sg, 1, direction,
                                             DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!dma_desc)
                return false;
index 3648c82a17fe3e20a5682f8fb1d42bcd06898f00..6ec7f838d7faa84383daa73f06a74aeab8d50e56 100644 (file)
@@ -786,9 +786,8 @@ static void xfer_work(struct work_struct *work)
        sg_dma_address(&sg) = pkt->dma + pkt->actual;
        sg_dma_len(&sg) = pkt->trans;
 
-       desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
-                                                 DMA_PREP_INTERRUPT |
-                                                 DMA_CTRL_ACK);
+       desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir,
+                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc)
                return;
 
index f23cae094f1b75e2781987705ef1ad115b540bb9..887df9d8142222fb17cfb508525f2d4b2bbbabcf 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 915943af3f21eed5f78d5fada3c3d42d20e74b6b..f49181c7311390c471b0abc6caa6d8ca6ae4de91 100644 (file)
@@ -67,6 +67,28 @@ static inline int wled_idc(int port)
        return ret;
 }
 
+static int backlight_power_set(struct pm860x_chip *chip, int port,
+               int on)
+{
+       int ret = -EINVAL;
+
+       switch (port) {
+       case PM8606_BACKLIGHT1:
+               ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) :
+                       pm8606_osc_disable(chip, WLED1_DUTY);
+               break;
+       case PM8606_BACKLIGHT2:
+               ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) :
+                       pm8606_osc_disable(chip, WLED2_DUTY);
+               break;
+       case PM8606_BACKLIGHT3:
+               ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) :
+                       pm8606_osc_disable(chip, WLED3_DUTY);
+               break;
+       }
+       return ret;
+}
+
 static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
 {
        struct pm860x_backlight_data *data = bl_get_data(bl);
@@ -79,6 +101,9 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
        else
                value = brightness;
 
+       if (brightness)
+               backlight_power_set(chip, data->port, 1);
+
        ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
        if (ret < 0)
                goto out;
@@ -115,6 +140,9 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
        if (ret < 0)
                goto out;
 
+       if (brightness == 0)
+               backlight_power_set(chip, data->port, 0);
+
        dev_dbg(chip->dev, "set brightness %d\n", value);
        data->current_brightness = value;
        return 0;
@@ -170,7 +198,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        struct backlight_device *bl;
        struct resource *res;
        struct backlight_properties props;
-       unsigned char value;
        char name[MFD_NAME_SIZE];
        int ret;
 
@@ -217,26 +244,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, bl);
 
-       /* Enable reference VSYS */
-       ret = pm860x_reg_read(data->i2c, PM8606_VSYS);
-       if (ret < 0)
-               goto out;
-       if ((ret & PM8606_VSYS_EN) == 0) {
-               value = ret | PM8606_VSYS_EN;
-               ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value);
-               if (ret < 0)
-                       goto out;
-       }
-       /* Enable reference OSC */
-       ret = pm860x_reg_read(data->i2c, PM8606_MISC);
-       if (ret < 0)
-               goto out;
-       if ((ret & PM8606_MISC_OSC_EN) == 0) {
-               value = ret | PM8606_MISC_OSC_EN;
-               ret = pm860x_reg_write(data->i2c, PM8606_MISC, value);
-               if (ret < 0)
-                       goto out;
-       }
        /* read current backlight */
        ret = pm860x_backlight_get_brightness(bl);
        if (ret < 0)
index be98d152b7fd9e798d0112e0a95192ebec57d56c..a523b255e124cc3ff44e4b39d15c9ba4a6f5761a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/atomic.h>
 
 static struct backlight_device *apple_backlight_device;
 
@@ -221,14 +222,32 @@ static struct acpi_driver apple_bl_driver = {
        },
 };
 
+static atomic_t apple_bl_registered = ATOMIC_INIT(0);
+
+int apple_bl_register(void)
+{
+       if (atomic_xchg(&apple_bl_registered, 1) == 0)
+               return acpi_bus_register_driver(&apple_bl_driver);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(apple_bl_register);
+
+void apple_bl_unregister(void)
+{
+       if (atomic_xchg(&apple_bl_registered, 0) == 1)
+               acpi_bus_unregister_driver(&apple_bl_driver);
+}
+EXPORT_SYMBOL_GPL(apple_bl_unregister);
+
 static int __init apple_bl_init(void)
 {
-       return acpi_bus_register_driver(&apple_bl_driver);
+       return apple_bl_register();
 }
 
 static void __exit apple_bl_exit(void)
 {
-       acpi_bus_unregister_driver(&apple_bl_driver);
+       apple_bl_unregister();
 }
 
 module_init(apple_bl_init);
index a2161f631a831f66992d4d84b9756c56b384de3f..2231aec23918fec6c1f65125421d1d35c229c759 100644 (file)
@@ -271,7 +271,7 @@ static int tosa_lcd_resume(struct spi_device *spi)
 }
 #else
 #define tosa_lcd_suspend       NULL
-#define tosa_lcd_reume NULL
+#define tosa_lcd_resume NULL
 #endif
 
 static struct spi_driver tosa_lcd_driver = {
index c826f2787badf14a55b8b4dcef94912448efb918..04e0cfbba5387eff7f26a671ca1f85dbc37abccc 100644 (file)
@@ -8,7 +8,6 @@
  *     archive for more details.
  */
 #include <linux/types.h>
-#include <asm/system.h>
 
 /*
  * Bt431 cursor generator registers, 32-bit aligned.
index b7591fea7add36aeb73ee5623002cf50f4433582..80f61b03e9ae1cb6cad5d5b6fb7afac6f88d22b8 100644 (file)
@@ -8,7 +8,6 @@
  *     archive for more details.
  */
 #include <linux/types.h>
-#include <asm/system.h>
 
 /*
  * Bt455 byte-wide registers, 32-bit aligned.
index 8745637e4b7e3811d27935b07dd1a24e6f3700c0..2e471c22abf5a5e835704e71767017923f747c0c 100644 (file)
@@ -77,7 +77,6 @@
 #include <linux/crc32.h> /* For counting font checksums */
 #include <asm/fb.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "fbcon.h"
 
index a122d9287d1659e60ad35f1b1cdf6bd8121366e6..6d1596629040794ca5147b3a477276d330536c8b 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/gio_device.h>
index 850380795b0555b02c4ef963206a9b6a4d726409..c1527f5b47eec53af0c54f33ff8e143afcf1c402 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/i2c-algo-bit.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #ifdef __arm__
 #include <asm/mach-types.h>
index ec56d2544c734aea151fd49ad97b88092b7beb5e..49e3dda1a361f72344a051bc7725dd3eebfc53b0 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/platform_device.h>
 
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 727a5149d81806be71c7b902be7d4a20b3309a2e..eec0d7b748eb9e503ea8a9ffa0d007b3a91ed0c5 100644 (file)
@@ -337,7 +337,7 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
 
        /* This enables the channel */
        if (mx3_fbi->cookie < 0) {
-               mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan,
+               mx3_fbi->txd = dmaengine_prep_slave_sg(dma_chan,
                      &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
                if (!mx3_fbi->txd) {
                        dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
@@ -1091,7 +1091,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
        if (mx3_fbi->txd)
                async_tx_ack(mx3_fbi->txd);
 
-       txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
+       txd = dmaengine_prep_slave_sg(dma_chan, sg +
                mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
        if (!txd) {
                dev_err(fbi->device,
index fb3f6739110532ddeda7008eecfefd5e277dd207..afc9521173effee7fbc5f5814194e25807e98db7 100644 (file)
@@ -71,7 +71,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
index fd227160037058e2a2220fa60f917056e5d630ef..4e5b960c32c88bbcab1ec7e31c1f1eb7772898d7 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bitops.h>
 #include <linux/mutex.h>
 
-#include <mach/io.h>
 #include <plat/vrfb.h>
 #include <plat/sdrc.h>
 
index 0c69fa20251b681bfc1eaa03d886c615f11bc8de..9b4a60b52a4ca9cf403f22a172e2bc5e3a93c270 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <video/pmag-ba-fb.h>
 
index 22fcb9a3d5c0d0088d6f1d8294783f91989c7564..4e7a9c46e1122a460957e0a3c22f6cf04b9d8961 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <video/pmagb-b-fb.h>
 
index f5a39f5aa90057c79fe9626f5783b0c52d51f3b2..a104e8cd2f54872cc4cb48f6d9f52acf26f08402 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/q40_master.h>
 #include <linux/fb.h>
 #include <linux/module.h>
index beb495044b240e5b2edc3f98656845756279e80c..cee7803a0a1c74fe09c1129f5edc927e58dfe86f 100644 (file)
@@ -56,7 +56,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
index 983d482fba403f00f866dde6b3ed6a6000472cc3..f70bcd2ff98ffdcb491840bb1a1a197d463f5bad 100644 (file)
@@ -9,5 +9,4 @@
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
 #include <linux/bug.h>
-#include <asm/system.h>
 
index 0e7366dfc9018d9b6c20491caf2b3cebb7ac3d62..37096246c93716ef314ad9fc4f519124cbc7456f 100644 (file)
@@ -55,6 +55,7 @@ comment "Watchdog Device Drivers"
 
 config SOFT_WATCHDOG
        tristate "Software watchdog"
+       select WATCHDOG_CORE
        help
          A software monitoring watchdog. This will fail to reboot your system
          from some situations that the hardware watchdog will recover
@@ -74,6 +75,7 @@ config WM831X_WATCHDOG
 config WM8350_WATCHDOG
        tristate "WM8350 watchdog"
        depends on MFD_WM8350
+       select WATCHDOG_CORE
        help
          Support for the watchdog in the WM8350 AudioPlus PMIC.  When
          the watchdog triggers the system will be reset.
@@ -217,6 +219,7 @@ config MPCORE_WATCHDOG
 config EP93XX_WATCHDOG
        tristate "EP93xx Watchdog"
        depends on ARCH_EP93XX
+       select WATCHDOG_CORE
        help
          Say Y here if to include support for the watchdog timer
          embedded in the Cirrus Logic EP93xx family of devices.
@@ -234,6 +237,7 @@ config OMAP_WATCHDOG
 config PNX4008_WATCHDOG
        tristate "PNX4008 and LPC32XX Watchdog"
        depends on ARCH_PNX4008 || ARCH_LPC32XX
+       select WATCHDOG_CORE
        help
          Say Y here if to include support for the watchdog timer
          in the PNX4008 or LPC32XX processor.
@@ -283,6 +287,7 @@ config COH901327_WATCHDOG
        bool "ST-Ericsson COH 901 327 watchdog"
        depends on ARCH_U300
        default y if MACH_U300
+       select WATCHDOG_CORE
        help
          Say Y here to include Watchdog timer support for the
          watchdog embedded into the ST-Ericsson U300 series platforms.
@@ -328,6 +333,7 @@ config TS72XX_WATCHDOG
 config MAX63XX_WATCHDOG
        tristate "Max63xx watchdog"
        depends on ARM && HAS_IOMEM
+       select WATCHDOG_CORE
        help
          Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
 
@@ -955,6 +961,7 @@ config INDYDOG
 config JZ4740_WDT
        tristate "Ingenic jz4740 SoC hardware watchdog"
        depends on MACH_JZ4740
+       select WATCHDOG_CORE
        help
          Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
 
@@ -996,6 +1003,7 @@ config AR7_WDT
 config TXX9_WDT
        tristate "Toshiba TXx9 Watchdog Timer"
        depends on CPU_TX39XX || CPU_TX49XX
+       select WATCHDOG_CORE
        help
          Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
 
index b6a2b58cbe64a0bf05bac1761fcb47090adb35b0..4397881c83f41fe86e070a932e69814fff12ab6e 100644 (file)
@@ -52,6 +52,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
 #include <linux/moduleparam.h>         /* For new moduleparam's */
@@ -70,7 +72,6 @@
 
 /* Module information */
 #define DRV_NAME "acquirewdt"
-#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Acquire WDT"
 /* There is no way to see what the correct time-out period is */
 #define WATCHDOG_HEARTBEAT 0
@@ -92,8 +93,8 @@ static int wdt_start = 0x443;
 module_param(wdt_start, int, 0);
 MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -208,8 +209,7 @@ static int acq_close(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                acq_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                acq_keepalive();
        }
        clear_bit(0, &acq_is_open);
@@ -246,27 +246,24 @@ static int __devinit acq_probe(struct platform_device *dev)
 
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-                       printk(KERN_ERR PFX
-                           "I/O address 0x%04x already in use\n", wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n", wdt_stop);
                        ret = -EIO;
                        goto out;
                }
        }
 
        if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                ret = -EIO;
                goto unreg_stop;
        }
        ret = misc_register(&acq_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_regions;
        }
-       printk(KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout);
+       pr_info("initialized. (nowayout=%d)\n", nowayout);
 
        return 0;
 unreg_regions:
@@ -308,8 +305,7 @@ static int __init acq_init(void)
 {
        int err;
 
-       printk(KERN_INFO
-             "WDT driver for Acquire single board computer initialising.\n");
+       pr_info("WDT driver for Acquire single board computer initialising\n");
 
        err = platform_driver_register(&acquirewdt_driver);
        if (err)
@@ -332,7 +328,7 @@ static void __exit acq_exit(void)
 {
        platform_device_unregister(acq_platform_device);
        platform_driver_unregister(&acquirewdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(acq_init);
index 4d40965d2c9fb5f808e52052b31b846825c6f778..64ae9e9fed94acdddab23d0d20ea50f771685ef3 100644 (file)
@@ -28,6 +28,8 @@
  *         add wdt_start and wdt_stop as parameters.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define DRV_NAME "advantechwdt"
-#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Advantech WDT"
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
@@ -77,8 +77,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=63, default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -207,8 +207,7 @@ static int advwdt_close(struct inode *inode, struct file *file)
        if (adv_expect_close == 42) {
                advwdt_disable();
        } else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                advwdt_ping();
        }
        clear_bit(0, &advwdt_is_open);
@@ -245,18 +244,15 @@ static int __devinit advwdt_probe(struct platform_device *dev)
 
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n",
+                              wdt_stop);
                        ret = -EIO;
                        goto out;
                }
        }
 
        if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                ret = -EIO;
                goto unreg_stop;
        }
@@ -265,18 +261,16 @@ static int __devinit advwdt_probe(struct platform_device *dev)
         * if not reset to the default */
        if (advwdt_set_heartbeat(timeout)) {
                advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be 1<=x<=63, using %d\n", timeout);
+               pr_info("timeout value must be 1<=x<=63, using %d\n", timeout);
        }
 
        ret = misc_register(&advwdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_regions;
        }
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 out:
        return ret;
@@ -318,8 +312,7 @@ static int __init advwdt_init(void)
 {
        int err;
 
-       printk(KERN_INFO
-            "WDT driver for Advantech single board computer initialising.\n");
+       pr_info("WDT driver for Advantech single board computer initialising\n");
 
        err = platform_driver_register(&advwdt_driver);
        if (err)
@@ -343,7 +336,7 @@ static void __exit advwdt_exit(void)
 {
        platform_device_unregister(advwdt_platform_device);
        platform_driver_unregister(&advwdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(advwdt_init);
index f16dcbd475fb7feb8c7314a1f0964a09310f0fa3..41b84936a521f62b81bec020646a7014e23e51bc 100644 (file)
@@ -7,6 +7,8 @@
  *     2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -22,7 +24,6 @@
 #include <linux/io.h>
 
 #define WATCHDOG_NAME "ALi_M1535"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60    /* 60 sec default timeout */
 
 /* internal variables */
@@ -39,8 +40,8 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in seconds. (0 < timeout < 18000, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -268,8 +269,7 @@ static int ali_release(struct inode *inode, struct file *file)
        if (ali_expect_release == 42)
                ali_stop();
        else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                ali_keepalive();
        }
        clear_bit(0, &ali_is_open);
@@ -399,9 +399,8 @@ static int __init watchdog_init(void)
           if not reset to the default */
        if (timeout < 1 || timeout >= 18000) {
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                    "timeout value must be 0 < timeout < 18000, using %d\n",
-                                                       timeout);
+               pr_info("timeout value must be 0 < timeout < 18000, using %d\n",
+                       timeout);
        }
 
        /* Calculate the watchdog's timeout */
@@ -409,20 +408,18 @@ static int __init watchdog_init(void)
 
        ret = register_reboot_notifier(&ali_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto out;
        }
 
        ret = misc_register(&ali_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
 out:
index 46f4b85b46de46706ff1b7f6972f624f9500c491..5eee55012e3375915b769e2bbcf05da9adbeff60 100644 (file)
@@ -19,6 +19,8 @@
  *                  -- Mike Waychison <michael.waychison@sun.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
-
-#define OUR_NAME "alim7101_wdt"
-#define PFX OUR_NAME ": "
 
 #define WDT_ENABLE 0x9C
 #define WDT_DISABLE 0x8C
@@ -79,8 +77,8 @@ static unsigned long wdt_is_open;
 static char wdt_expect_close;
 static struct pci_dev *alim7101_pmu;
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -112,8 +110,7 @@ static void wdt_timer_ping(unsigned long data)
                                        ALI_7101_GPIO_O, tmp & ~0x20);
                }
        } else {
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
        }
        /* Re-set the timer interval */
        mod_timer(&timer, jiffies + WDT_INTERVAL);
@@ -162,7 +159,7 @@ static void wdt_startup(void)
        /* Start the timer */
        mod_timer(&timer, jiffies + WDT_INTERVAL);
 
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 static void wdt_turnoff(void)
@@ -170,7 +167,7 @@ static void wdt_turnoff(void)
        /* Stop the timer */
        del_timer_sync(&timer);
        wdt_change(WDT_DISABLE);
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
 }
 
 static void wdt_keepalive(void)
@@ -226,8 +223,7 @@ static int fop_close(struct inode *inode, struct file *file)
                wdt_turnoff();
        else {
                /* wim: shouldn't there be a: del_timer(&timer); */
-               printk(KERN_CRIT PFX
-                 "device file closed unexpectedly. Will not stop the WDT!\n");
+               pr_crit("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &wdt_is_open);
        wdt_expect_close = 0;
@@ -322,8 +318,7 @@ static int wdt_notify_sys(struct notifier_block *this,
                 * watchdog on reboot with no heartbeat
                 */
                wdt_change(WDT_ENABLE);
-               printk(KERN_INFO PFX "Watchdog timer is now enabled "
-                       "with no heartbeat - should reboot in ~1 second.\n");
+               pr_info("Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second\n");
        }
        return NOTIFY_DONE;
 }
@@ -352,12 +347,11 @@ static int __init alim7101_wdt_init(void)
        struct pci_dev *ali1543_south;
        char tmp;
 
-       printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n");
+       pr_info("Steve Hill <steve@navaho.co.uk>\n");
        alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
                NULL);
        if (!alim7101_pmu) {
-               printk(KERN_INFO PFX
-                       "ALi M7101 PMU not present - WDT not set\n");
+               pr_info("ALi M7101 PMU not present - WDT not set\n");
                return -EBUSY;
        }
 
@@ -367,56 +361,46 @@ static int __init alim7101_wdt_init(void)
        ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
                NULL);
        if (!ali1543_south) {
-               printk(KERN_INFO PFX
-                       "ALi 1543 South-Bridge not present - WDT not set\n");
+               pr_info("ALi 1543 South-Bridge not present - WDT not set\n");
                goto err_out;
        }
        pci_read_config_byte(ali1543_south, 0x5e, &tmp);
        pci_dev_put(ali1543_south);
        if ((tmp & 0x1e) == 0x00) {
                if (!use_gpio) {
-                       printk(KERN_INFO PFX
-                               "Detected old alim7101 revision 'a1d'.  "
-                               "If this is a cobalt board, set the 'use_gpio' "
-                               "module parameter.\n");
+                       pr_info("Detected old alim7101 revision 'a1d'.  If this is a cobalt board, set the 'use_gpio' module parameter.\n");
                        goto err_out;
                }
                nowayout = 1;
        } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
-               printk(KERN_INFO PFX
-                       "ALi 1543 South-Bridge does not have the correct "
-                       "revision number (???1001?) - WDT not set\n");
+               pr_info("ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
                goto err_out;
        }
 
        if (timeout < 1 || timeout > 3600) {
                /* arbitrary upper limit */
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 3600, using %d\n",
-                                                               timeout);
+               pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
+                       timeout);
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
        if (nowayout)
                __module_get(THIS_MODULE);
 
-       printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. "
-                                       "timeout=%d sec (nowayout=%d)\n",
+       pr_info("WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
        return 0;
 
index 502773ad5acda8889ec5c0770ac38702d6db16de..639ae9a23fbc3361da6720f4b94c8e16af39c0e1 100644 (file)
@@ -23,6 +23,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
@@ -39,7 +41,6 @@
 #include <asm/addrspace.h>
 #include <asm/mach-ar7/ar7.h>
 
-#define DRVNAME "ar7_wdt"
 #define LONGNAME "TI AR7 Watchdog Timer"
 
 MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
@@ -51,8 +52,8 @@ static int margin = 60;
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 #define READ_REG(x) readl((void __iomem *)&(x))
@@ -93,7 +94,7 @@ static void ar7_wdt_kick(u32 value)
                        return;
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT kick reg\n");
+       pr_err("failed to unlock WDT kick reg\n");
 }
 
 static void ar7_wdt_prescale(u32 value)
@@ -106,7 +107,7 @@ static void ar7_wdt_prescale(u32 value)
                        return;
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT prescale reg\n");
+       pr_err("failed to unlock WDT prescale reg\n");
 }
 
 static void ar7_wdt_change(u32 value)
@@ -119,7 +120,7 @@ static void ar7_wdt_change(u32 value)
                        return;
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT change reg\n");
+       pr_err("failed to unlock WDT change reg\n");
 }
 
 static void ar7_wdt_disable(u32 value)
@@ -135,7 +136,7 @@ static void ar7_wdt_disable(u32 value)
                        }
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT disable reg\n");
+       pr_err("failed to unlock WDT disable reg\n");
 }
 
 static void ar7_wdt_update_margin(int new_margin)
@@ -151,21 +152,20 @@ static void ar7_wdt_update_margin(int new_margin)
                change = 0xffff;
        ar7_wdt_change(change);
        margin = change * prescale_value / vbus_rate;
-       printk(KERN_INFO DRVNAME
-              ": timer margin %d seconds (prescale %d, change %d, freq %d)\n",
-              margin, prescale_value, change, vbus_rate);
+       pr_info("timer margin %d seconds (prescale %d, change %d, freq %d)\n",
+               margin, prescale_value, change, vbus_rate);
 }
 
 static void ar7_wdt_enable_wdt(void)
 {
-       printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
+       pr_debug("enabling watchdog timer\n");
        ar7_wdt_disable(1);
        ar7_wdt_kick(1);
 }
 
 static void ar7_wdt_disable_wdt(void)
 {
-       printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
+       pr_debug("disabling watchdog timer\n");
        ar7_wdt_disable(0);
 }
 
@@ -183,9 +183,7 @@ static int ar7_wdt_open(struct inode *inode, struct file *file)
 static int ar7_wdt_release(struct inode *inode, struct file *file)
 {
        if (!expect_close)
-               printk(KERN_WARNING DRVNAME
-               ": watchdog device closed unexpectedly,"
-               "will not disable the watchdog timer\n");
+               pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer\n");
        else if (!nowayout)
                ar7_wdt_disable_wdt();
        clear_bit(0, &wdt_is_open);
@@ -283,28 +281,28 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
        ar7_regs_wdt =
                platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
        if (!ar7_regs_wdt) {
-               printk(KERN_ERR DRVNAME ": could not get registers resource\n");
+               pr_err("could not get registers resource\n");
                rc = -ENODEV;
                goto out;
        }
 
        if (!request_mem_region(ar7_regs_wdt->start,
                                resource_size(ar7_regs_wdt), LONGNAME)) {
-               printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+               pr_warn("watchdog I/O region busy\n");
                rc = -EBUSY;
                goto out;
        }
 
        ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
        if (!ar7_wdt) {
-               printk(KERN_ERR DRVNAME ": could not ioremap registers\n");
+               pr_err("could not ioremap registers\n");
                rc = -ENXIO;
                goto out_mem_region;
        }
 
        vbus_clk = clk_get(NULL, "vbus");
        if (IS_ERR(vbus_clk)) {
-               printk(KERN_ERR DRVNAME ": could not get vbus clock\n");
+               pr_err("could not get vbus clock\n");
                rc = PTR_ERR(vbus_clk);
                goto out_mem_region;
        }
@@ -315,7 +313,7 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
 
        rc = misc_register(&ar7_wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+               pr_err("unable to register misc device\n");
                goto out_alloc;
        }
        goto out;
index 4ca5d40304b255a7b9f810ba4a27b8dfd7b69e20..2896430ce42ca2f7a304fc7da1200c9ea6c3f7e6 100644 (file)
@@ -45,8 +45,8 @@ MODULE_PARM_DESC(timeout,
                "Timeout value. Limited to be 1 or 2 seconds. (default="
                __MODULE_STRING(TIMEOUT_DEFAULT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 7ceefd29ae147f689f856231369dd4ef83f8e0a6..7ef99a169e3bbaf6e433abe4a7591b576a35ad75 100644 (file)
@@ -9,6 +9,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #define WDT_MAX_TIME           256     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
                                __MODULE_STRING(WDT_DEFAULT_TIME) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -209,8 +211,8 @@ static int __devinit at91wdt_probe(struct platform_device *pdev)
        if (res)
                return res;
 
-       printk(KERN_INFO "AT91 Watchdog Timer enabled (%d seconds%s)\n",
-                               wdt_time, nowayout ? ", nowayout" : "");
+       pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n",
+               wdt_time, nowayout ? ", nowayout" : "");
        return 0;
 }
 
@@ -268,8 +270,8 @@ static int __init at91_wdt_init(void)
           if not reset to the default */
        if (at91_wdt_settimeout(wdt_time)) {
                at91_wdt_settimeout(WDT_DEFAULT_TIME);
-               pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256"
-                                               ", using %d\n", wdt_time);
+               pr_info("wdt_time value must be 1 <= wdt_time <= 256, using %d\n",
+                       wdt_time);
        }
 
        return platform_driver_register(&at91wdt_driver);
index 00562566ef5f2773b006c80a7981cb5da56c7867..05e1be85fdeeda07a21651ee1a4096bf6b77c06d 100644 (file)
@@ -15,6 +15,8 @@
  * bootloader doesn't write to this register.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -60,8 +62,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
        "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -96,7 +98,7 @@ static void at91_ping(unsigned long data)
                at91_wdt_reset();
                mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
        } else
-               printk(KERN_CRIT DRV_NAME": I will reset your machine !\n");
+               pr_crit("I will reset your machine !\n");
 }
 
 /*
@@ -140,7 +142,7 @@ static int at91_wdt_settimeout(unsigned int timeout)
        /* Check if disabled */
        mr = wdt_read(AT91_WDT_MR);
        if (mr & AT91_WDT_WDDIS) {
-               printk(KERN_ERR DRV_NAME": sorry, watchdog is disabled\n");
+               pr_err("sorry, watchdog is disabled\n");
                return -EIO;
        }
 
@@ -283,7 +285,7 @@ static int __init at91wdt_probe(struct platform_device *pdev)
        setup_timer(&at91wdt_private.timer, at91_ping, 0);
        mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
 
-       printk(KERN_INFO DRV_NAME " enabled (heartbeat=%d sec, nowayout=%d)\n",
+       pr_info("enabled (heartbeat=%d sec, nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
index 9db808349f8b1e6dc29a892920602fb497f5ef6d..1f9371f49c402c71422edc364871fa8c3bf9c149 100644 (file)
@@ -17,6 +17,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -45,8 +47,8 @@
 #define WDOG_CTRL_ACTION_NMI   2       /* NMI */
 #define WDOG_CTRL_ACTION_FCR   3       /* full chip reset */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                           "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -114,8 +116,7 @@ static int ath79_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags))
                ath79_wdt_disable();
        else {
-               pr_crit(DRIVER_NAME ": device closed unexpectedly, "
-                       "watchdog timer will not stop!\n");
+               pr_crit("device closed unexpectedly, watchdog timer will not stop!\n");
                ath79_wdt_keepalive();
        }
 
index 5c5f4b14fd05aee17e1e6d1f30743f8a3735a1c9..bc0e91e78e863dcc4504d2ab743e37564381dde7 100644 (file)
@@ -10,6 +10,8 @@
  *  2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #define WDT_MAX_TIME           255     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
                                __MODULE_STRING(WDT_DEFAULT_TIME) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -91,7 +93,7 @@ static void bcm47xx_timer_tick(unsigned long unused)
                bcm47xx_wdt_hw_start();
                mod_timer(&wdt_timer, jiffies + HZ);
        } else {
-               printk(KERN_CRIT DRV_NAME "Watchdog will fire soon!!!\n");
+               pr_crit("Watchdog will fire soon!!!\n");
        }
 }
 
@@ -140,8 +142,7 @@ static int bcm47xx_wdt_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                bcm47xx_wdt_stop();
        } else {
-               printk(KERN_CRIT DRV_NAME
-                       ": Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                bcm47xx_wdt_start();
        }
 
@@ -270,8 +271,7 @@ static int __init bcm47xx_wdt_init(void)
 
        if (bcm47xx_wdt_settimeout(wdt_time)) {
                bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);
-               printk(KERN_INFO DRV_NAME ": "
-                       "wdt_time value must be 0 < wdt_time < %d, using %d\n",
+               pr_info("wdt_time value must be 0 < wdt_time < %d, using %d\n",
                        (WDT_MAX_TIME + 1), wdt_time);
        }
 
@@ -285,8 +285,8 @@ static int __init bcm47xx_wdt_init(void)
                return ret;
        }
 
-       printk(KERN_INFO "BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
-                               wdt_time, nowayout ? ", nowayout" : "");
+       pr_info("BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
+               wdt_time, nowayout ? ", nowayout" : "");
        return 0;
 }
 
index 8dc7de641e2610f1042cd8a09f7170ed2195df34..8379dc32fd908f9bf0e76532ca27d847ca145fd3 100644 (file)
@@ -10,6 +10,8 @@
  *  2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -50,8 +52,8 @@ static struct {
 static int expect_close;
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -82,7 +84,7 @@ static void bcm63xx_timer_tick(unsigned long unused)
                bcm63xx_wdt_hw_start();
                mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ);
        } else
-               printk(KERN_CRIT PFX ": watchdog will restart system\n");
+               pr_crit("watchdog will restart system\n");
 }
 
 static void bcm63xx_wdt_pet(void)
@@ -126,8 +128,7 @@ static int bcm63xx_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                bcm63xx_wdt_pause();
        else {
-               printk(KERN_CRIT PFX
-                       ": Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                bcm63xx_wdt_start();
        }
        clear_bit(0, &bcm63xx_wdt_device.inuse);
index b9fa9b71583a68b49ed1e8026329c1cc24bb431c..38bc383e0677228abbfd3109cd1774e0c32e31e7 100644 (file)
@@ -11,6 +11,8 @@
  * Licensed under the GPL-2 or later.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #define stamp(fmt, args...) \
        pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
 #define stampit() stamp("here i am")
-#define pr_devinit(fmt, args...) \
-       ({ static const __devinitconst char __fmt[] = fmt; \
-       printk(__fmt, ## args); })
-#define pr_init(fmt, args...) \
-       ({ static const __initconst char __fmt[] = fmt; \
-       printk(__fmt, ## args); })
 
 #define WATCHDOG_NAME "bfin-wdt"
-#define PFX WATCHDOG_NAME ": "
 
 /* The BF561 has two watchdogs (one per core), but since Linux
  * only runs on core A, we'll just work with that one.
@@ -54,7 +49,7 @@
 #define WATCHDOG_TIMEOUT 20
 
 static unsigned int timeout = WATCHDOG_TIMEOUT;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static const struct watchdog_info bfin_wdt_info;
 static unsigned long open_check;
 static char expect_close;
@@ -126,7 +121,7 @@ static int bfin_wdt_set_timeout(unsigned long t)
        stamp("maxtimeout=%us newtimeout=%lus (cnt=%#x)", max_t, t, cnt);
 
        if (t > max_t) {
-               printk(KERN_WARNING PFX "timeout value is too large\n");
+               pr_warn("timeout value is too large\n");
                return -EINVAL;
        }
 
@@ -182,8 +177,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                bfin_wdt_stop();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                bfin_wdt_keepalive();
        }
        expect_close = 0;
@@ -368,14 +362,13 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
 
        ret = misc_register(&bfin_wdt_miscdev);
        if (ret) {
-               pr_devinit(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                return ret;
        }
 
-       pr_devinit(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
-              timeout, nowayout);
+       pr_info("initialized: timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
        return 0;
 }
@@ -439,14 +432,14 @@ static int __init bfin_wdt_init(void)
         */
        ret = platform_driver_register(&bfin_wdt_driver);
        if (ret) {
-               pr_init(KERN_ERR PFX "unable to register driver\n");
+               pr_err("unable to register driver\n");
                return ret;
        }
 
        bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME,
                                                                -1, NULL, 0);
        if (IS_ERR(bfin_wdt_device)) {
-               pr_init(KERN_ERR PFX "unable to register device\n");
+               pr_err("unable to register device\n");
                platform_driver_unregister(&bfin_wdt_driver);
                return PTR_ERR(bfin_wdt_device);
        }
@@ -479,7 +472,7 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 7c0fdfca26469be5643f994a88c950c2855e4768..ce0ab4415eff2cb0fb4c0fc3b9d6deb9ca14e010 100644 (file)
@@ -12,6 +12,8 @@
  * option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
@@ -21,7 +23,6 @@
 #include <linux/uaccess.h>
 
 #include <asm/reg_booke.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/div64.h>
 
@@ -225,8 +226,8 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
        if (booke_wdt_enabled == 0) {
                booke_wdt_enabled = 1;
                on_each_cpu(__booke_wdt_enable, NULL, 0);
-               pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
-                       period_to_sec(booke_wdt_period));
+               pr_debug("watchdog enabled (timeout = %llu sec)\n",
+                        period_to_sec(booke_wdt_period));
        }
        spin_unlock(&booke_wdt_lock);
 
@@ -243,7 +244,7 @@ static int booke_wdt_release(struct inode *inode, struct file *file)
         */
        on_each_cpu(__booke_wdt_disable, NULL, 0);
        booke_wdt_enabled = 0;
-       pr_debug("booke_wdt: watchdog disabled\n");
+       pr_debug("watchdog disabled\n");
 #endif
 
        clear_bit(0, &wdt_is_active);
@@ -275,19 +276,19 @@ static int __init booke_wdt_init(void)
 {
        int ret = 0;
 
-       pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n");
+       pr_info("powerpc book-e watchdog driver loaded\n");
        ident.firmware_version = cur_cpu_spec->pvr_value;
 
        ret = misc_register(&booke_wdt_miscdev);
        if (ret) {
-               pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n",
+               pr_err("cannot register device (minor=%u, ret=%i)\n",
                       WATCHDOG_MINOR, ret);
                return ret;
        }
 
        spin_lock(&booke_wdt_lock);
        if (booke_wdt_enabled == 1) {
-               pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
+               pr_info("watchdog enabled (timeout = %llu sec)\n",
                        period_to_sec(booke_wdt_period));
                on_each_cpu(__booke_wdt_enable, NULL, 0);
        }
index 5b89f7d6cd0ff4bb6d2f305e025b2ad3ebd18c5b..6876430a9f5e49a62eb1b755ee0c68a9e89c94e8 100644 (file)
@@ -8,17 +8,15 @@
  */
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
-#include <linux/uaccess.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/err.h>
 
 #define DRV_NAME "WDOG COH 901 327"
 
 #define U300_WDOG_IFR_WILL_BARK_IRQ_FORCE_ENABLE                       0x0001U
 
 /* Default timeout in seconds = 1 minute */
-static int margin = 60;
+static unsigned int margin = 60;
 static resource_size_t phybase;
 static resource_size_t physize;
 static int irq;
 static void __iomem *virtbase;
-static unsigned long coh901327_users;
-static unsigned long boot_status;
 static struct device *parent;
 
 /*
@@ -155,34 +151,35 @@ static void coh901327_disable(void)
                        __func__, val);
 }
 
-static void coh901327_start(void)
+static int coh901327_start(struct watchdog_device *wdt_dev)
 {
-       coh901327_enable(margin * 100);
+       coh901327_enable(wdt_dev->timeout * 100);
+       return 0;
+}
+
+static int coh901327_stop(struct watchdog_device *wdt_dev)
+{
+       coh901327_disable();
+       return 0;
 }
 
-static void coh901327_keepalive(void)
+static int coh901327_ping(struct watchdog_device *wdd)
 {
        clk_enable(clk);
        /* Feed the watchdog */
        writew(U300_WDOG_FR_FEED_RESTART_TIMER,
               virtbase + U300_WDOG_FR);
        clk_disable(clk);
+       return 0;
 }
 
-static int coh901327_settimeout(int time)
+static int coh901327_settimeout(struct watchdog_device *wdt_dev,
+                               unsigned int time)
 {
-       /*
-        * Max margin is 327 since the 10ms
-        * timeout register is max
-        * 0x7FFF = 327670ms ~= 327s.
-        */
-       if (time <= 0 || time > 327)
-               return -EINVAL;
-
-       margin = time;
+       wdt_dev->timeout = time;
        clk_enable(clk);
        /* Set new timeout value */
-       writew(margin * 100, virtbase + U300_WDOG_TR);
+       writew(time * 100, virtbase + U300_WDOG_TR);
        /* Feed the dog */
        writew(U300_WDOG_FR_FEED_RESTART_TIMER,
               virtbase + U300_WDOG_FR);
@@ -190,6 +187,23 @@ static int coh901327_settimeout(int time)
        return 0;
 }
 
+static unsigned int coh901327_gettimeleft(struct watchdog_device *wdt_dev)
+{
+       u16 val;
+
+       clk_enable(clk);
+       /* Read repeatedly until the value is stable! */
+       val = readw(virtbase + U300_WDOG_CR);
+       while (val & U300_WDOG_CR_VALID_IND)
+               val = readw(virtbase + U300_WDOG_CR);
+       val &= U300_WDOG_CR_COUNT_VALUE_MASK;
+       clk_disable(clk);
+       if (val != 0)
+               val /= 100;
+
+       return val;
+}
+
 /*
  * This interrupt occurs 10 ms before the watchdog WILL bark.
  */
@@ -218,130 +232,35 @@ static irqreturn_t coh901327_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-/*
- * Allow only one user (daemon) to open the watchdog
- */
-static int coh901327_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(1, &coh901327_users))
-               return -EBUSY;
-       coh901327_start();
-       return nonseekable_open(inode, file);
-}
-
-static int coh901327_release(struct inode *inode, struct file *file)
-{
-       clear_bit(1, &coh901327_users);
-       coh901327_disable();
-       return 0;
-}
-
-static ssize_t coh901327_write(struct file *file, const char __user *data,
-                              size_t len, loff_t *ppos)
-{
-       if (len)
-               coh901327_keepalive();
-       return len;
-}
-
-static long coh901327_ioctl(struct file *file, unsigned int cmd,
-                           unsigned long arg)
-{
-       int ret = -ENOTTY;
-       u16 val;
-       int time;
-       int new_options;
-       union {
-               struct watchdog_info __user *ident;
-               int __user *i;
-       } uarg;
-       static const struct watchdog_info ident = {
-               .options                = WDIOF_CARDRESET |
-                                         WDIOF_SETTIMEOUT |
-                                         WDIOF_KEEPALIVEPING,
-               .identity               = "COH 901 327 Watchdog",
-               .firmware_version       = 1,
-       };
-       uarg.i = (int __user *)arg;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user(uarg.ident, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, uarg.i);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, uarg.i);
-               break;
-
-       case WDIOC_SETOPTIONS:
-               ret = get_user(new_options, uarg.i);
-               if (ret)
-                       break;
-               if (new_options & WDIOS_DISABLECARD)
-                       coh901327_disable();
-               if (new_options & WDIOS_ENABLECARD)
-                       coh901327_start();
-               ret = 0;
-               break;
-
-       case WDIOC_KEEPALIVE:
-               coh901327_keepalive();
-               ret = 0;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, uarg.i);
-               if (ret)
-                       break;
-
-               ret = coh901327_settimeout(time);
-               if (ret)
-                       break;
-               /* Then fall through to return set value */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(margin, uarg.i);
-               break;
-
-       case WDIOC_GETTIMELEFT:
-               clk_enable(clk);
-               /* Read repeatedly until the value is stable! */
-               val = readw(virtbase + U300_WDOG_CR);
-               while (val & U300_WDOG_CR_VALID_IND)
-                       val = readw(virtbase + U300_WDOG_CR);
-               val &= U300_WDOG_CR_COUNT_VALUE_MASK;
-               clk_disable(clk);
-               if (val != 0)
-                       val /= 100;
-               ret = put_user(val, uarg.i);
-               break;
-       }
-       return ret;
-}
+static const struct watchdog_info coh901327_ident = {
+       .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity = DRV_NAME,
+};
 
-static const struct file_operations coh901327_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = coh901327_write,
-       .unlocked_ioctl = coh901327_ioctl,
-       .open           = coh901327_open,
-       .release        = coh901327_release,
+static struct watchdog_ops coh901327_ops = {
+       .owner = THIS_MODULE,
+       .start = coh901327_start,
+       .stop = coh901327_stop,
+       .ping = coh901327_ping,
+       .set_timeout = coh901327_settimeout,
+       .get_timeleft = coh901327_gettimeleft,
 };
 
-static struct miscdevice coh901327_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &coh901327_fops,
+static struct watchdog_device coh901327_wdt = {
+       .info = &coh901327_ident,
+       .ops = &coh901327_ops,
+       /*
+        * Max timeout is 327 since the 10ms
+        * timeout register is max
+        * 0x7FFF = 327670ms ~= 327s.
+        */
+       .min_timeout = 0,
+       .max_timeout = 327,
 };
 
 static int __exit coh901327_remove(struct platform_device *pdev)
 {
-       misc_deregister(&coh901327_miscdev);
+       watchdog_unregister_device(&coh901327_wdt);
        coh901327_disable();
        free_irq(irq, pdev);
        clk_put(clk);
@@ -350,7 +269,6 @@ static int __exit coh901327_remove(struct platform_device *pdev)
        return 0;
 }
 
-
 static int __init coh901327_probe(struct platform_device *pdev)
 {
        int ret;
@@ -393,7 +311,7 @@ static int __init coh901327_probe(struct platform_device *pdev)
        case U300_WDOG_SR_STATUS_TIMED_OUT:
                dev_info(&pdev->dev,
                        "watchdog timed out since last chip reset!\n");
-               boot_status = WDIOF_CARDRESET;
+               coh901327_wdt.bootstatus |= WDIOF_CARDRESET;
                /* Status will be cleared below */
                break;
        case U300_WDOG_SR_STATUS_NORMAL:
@@ -435,7 +353,11 @@ static int __init coh901327_probe(struct platform_device *pdev)
 
        clk_disable(clk);
 
-       ret = misc_register(&coh901327_miscdev);
+       if (margin < 1 || margin > 327)
+               margin = 60;
+       coh901327_wdt.timeout = margin;
+
+       ret = watchdog_register_device(&coh901327_wdt);
        if (ret == 0)
                dev_info(&pdev->dev,
                         "initialized. timer margin=%d sec\n", margin);
@@ -543,8 +465,8 @@ module_exit(coh901327_exit);
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 MODULE_DESCRIPTION("COH 901 327 Watchdog");
 
-module_param(margin, int, 0);
+module_param(margin, uint, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
 
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform:coh901327-watchdog");
index 251c863d71ddc123481a1bb4743973c8ebde02b6..7e888393de1ffcd652f73d3078dede07a540b4a8 100644 (file)
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -71,7 +73,7 @@ static struct {
 static void cpu5wdt_trigger(unsigned long unused)
 {
        if (verbose > 2)
-               printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
+               pr_debug("trigger at %i ticks\n", ticks);
 
        if (cpu5wdt_device.running)
                ticks--;
@@ -96,7 +98,7 @@ static void cpu5wdt_reset(void)
        ticks = cpu5wdt_device.default_ticks;
 
        if (verbose)
-               printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
+               pr_debug("reset (%i ticks)\n", (int) ticks);
 
 }
 
@@ -129,7 +131,7 @@ static int cpu5wdt_stop(void)
        ticks = cpu5wdt_device.default_ticks;
        spin_unlock_irqrestore(&cpu5wdt_lock, flags);
        if (verbose)
-               printk(KERN_CRIT PFX "stop not possible\n");
+               pr_crit("stop not possible\n");
        return -EIO;
 }
 
@@ -219,8 +221,7 @@ static int __devinit cpu5wdt_init(void)
        int err;
 
        if (verbose)
-               printk(KERN_DEBUG PFX
-                               "port=0x%x, verbose=%i\n", port, verbose);
+               pr_debug("port=0x%x, verbose=%i\n", port, verbose);
 
        init_completion(&cpu5wdt_device.stop);
        cpu5wdt_device.queue = 0;
@@ -228,7 +229,7 @@ static int __devinit cpu5wdt_init(void)
        cpu5wdt_device.default_ticks = ticks;
 
        if (!request_region(port, CPU5WDT_EXTENT, PFX)) {
-               printk(KERN_ERR PFX "request_region failed\n");
+               pr_err("request_region failed\n");
                err = -EBUSY;
                goto no_port;
        }
@@ -237,16 +238,16 @@ static int __devinit cpu5wdt_init(void)
        val = inb(port + CPU5WDT_STATUS_REG);
        val = (val >> 2) & 1;
        if (!val)
-               printk(KERN_INFO PFX "sorry, was my fault\n");
+               pr_info("sorry, was my fault\n");
 
        err = misc_register(&cpu5wdt_misc);
        if (err < 0) {
-               printk(KERN_ERR PFX "misc_register failed\n");
+               pr_err("misc_register failed\n");
                goto no_misc;
        }
 
 
-       printk(KERN_INFO PFX "init success\n");
+       pr_info("init success\n");
        return 0;
 
 no_misc:
index 1b793dfd868fdbe009c244e3cf0a5150bc431035..95b1b954de1bb336076c44a564f0682be87233ed 100644 (file)
@@ -14,6 +14,8 @@
  * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -35,7 +37,6 @@
 #include <asm/watchdog.h>
 
 #define DRIVER_NAME    "cpwd"
-#define PFX            DRIVER_NAME ": "
 
 #define WD_OBPNAME     "watchdog"
 #define WD_BADMODEL    "SUNW,501-5336"
@@ -385,8 +386,7 @@ static int cpwd_open(struct inode *inode, struct file *f)
        if (!p->initialized) {
                if (request_irq(p->irq, &cpwd_interrupt,
                                IRQF_SHARED, DRIVER_NAME, p)) {
-                       printk(KERN_ERR PFX "Cannot register IRQ %d\n",
-                               p->irq);
+                       pr_err("Cannot register IRQ %d\n", p->irq);
                        mutex_unlock(&cpwd_mutex);
                        return -EBUSY;
                }
@@ -542,7 +542,7 @@ static int __devinit cpwd_probe(struct platform_device *op)
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        err = -ENOMEM;
        if (!p) {
-               printk(KERN_ERR PFX "Unable to allocate struct cpwd.\n");
+               pr_err("Unable to allocate struct cpwd\n");
                goto out;
        }
 
@@ -553,14 +553,14 @@ static int __devinit cpwd_probe(struct platform_device *op)
        p->regs = of_ioremap(&op->resource[0], 0,
                             4 * WD_TIMER_REGSZ, DRIVER_NAME);
        if (!p->regs) {
-               printk(KERN_ERR PFX "Unable to map registers.\n");
+               pr_err("Unable to map registers\n");
                goto out_free;
        }
 
        options = of_find_node_by_path("/options");
        err = -ENODEV;
        if (!options) {
-               printk(KERN_ERR PFX "Unable to find /options node.\n");
+               pr_err("Unable to find /options node\n");
                goto out_iounmap;
        }
 
@@ -605,8 +605,8 @@ static int __devinit cpwd_probe(struct platform_device *op)
 
                err = misc_register(&p->devs[i].misc);
                if (err) {
-                       printk(KERN_ERR "Could not register misc device for "
-                              "dev %d\n", i);
+                       pr_err("Could not register misc device for dev %d\n",
+                              i);
                        goto out_unregister;
                }
        }
@@ -617,8 +617,8 @@ static int __devinit cpwd_probe(struct platform_device *op)
                cpwd_timer.data         = (unsigned long) p;
                cpwd_timer.expires      = WD_BTIMEOUT;
 
-               printk(KERN_INFO PFX "PLD defect workaround enabled for "
-                      "model " WD_BADMODEL ".\n");
+               pr_info("PLD defect workaround enabled for model %s\n",
+                       WD_BADMODEL);
        }
 
        dev_set_drvdata(&op->dev, p);
index 63d7b58f1c7d35edb71baee715d6a18c930c9783..06de1211a444db37244e5f180c4aa926af349b86 100644 (file)
@@ -16,7 +16,8 @@
  * If we receive an expected close for the watchdog then we keep the timer
  * running, otherwise the timer is stopped and the watchdog will expire.
  */
-#define pr_fmt(fmt) "dw_wdt: " fmt
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/bitops.h>
 #include <linux/clk.h>
@@ -45,8 +46,8 @@
 /* The maximum TOP (timeout period) value that can be set in the watchdog. */
 #define DW_WDT_MAX_TOP         15
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 09cd888db6197238200b270f24a9bc00b257cbd5..77050037597a08603c1cbbe6d0e6cf9acb32efee 100644 (file)
@@ -8,6 +8,9 @@
  * Authors: Ray Lehtiniemi <rayl@mail.com>,
  *     Alessandro Zummo <a.zummo@towertech.it>
  *
+ * Copyright (c) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *     Convert to a platform device and use the watchdog framework API
+ *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
 
 #include <linux/platform_device.h>
 #include <linux/module.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/timer.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
 
-#define WDT_VERSION    "0.3"
-#define PFX            "ep93xx_wdt: "
+#define WDT_VERSION    "0.4"
 
 /* default timeout (secs) */
 #define WDT_TIMEOUT 30
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-static int timeout = WDT_TIMEOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+static unsigned int timeout = WDT_TIMEOUT;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+       "Watchdog timeout in seconds. (1<=timeout<=3600, default="
+                               __MODULE_STRING(WDT_TIMEOUT) ")");
 
 static void __iomem *mmio_base;
 static struct timer_list timer;
 static unsigned long next_heartbeat;
-static unsigned long wdt_status;
-static unsigned long boot_status;
-
-#define WDT_IN_USE             0
-#define WDT_OK_TO_CLOSE                1
 
 #define EP93XX_WATCHDOG                0x00
 #define EP93XX_WDSTATUS                0x04
 
-/* reset the wdt every ~200ms */
+/* reset the wdt every ~200ms - the heartbeat of the device is 0.250 seconds*/
 #define WDT_INTERVAL (HZ/5)
 
-static void wdt_enable(void)
+static void ep93xx_wdt_timer_ping(unsigned long data)
 {
-       writel(0xaaaa, mmio_base + EP93XX_WATCHDOG);
-}
-
-static void wdt_disable(void)
-{
-       writel(0xaa55, mmio_base + EP93XX_WATCHDOG);
-}
+       if (time_before(jiffies, next_heartbeat))
+               writel(0x5555, mmio_base + EP93XX_WATCHDOG);
 
-static inline void wdt_ping(void)
-{
-       writel(0x5555, mmio_base + EP93XX_WATCHDOG);
+       /* Re-set the timer interval */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
 }
 
-static void wdt_startup(void)
+static int ep93xx_wdt_start(struct watchdog_device *wdd)
 {
        next_heartbeat = jiffies + (timeout * HZ);
 
-       wdt_enable();
+       writel(0xaaaa, mmio_base + EP93XX_WATCHDOG);
        mod_timer(&timer, jiffies + WDT_INTERVAL);
+
+       return 0;
 }
 
-static void wdt_shutdown(void)
+static int ep93xx_wdt_stop(struct watchdog_device *wdd)
 {
        del_timer_sync(&timer);
-       wdt_disable();
+       writel(0xaa55, mmio_base + EP93XX_WATCHDOG);
+
+       return 0;
 }
 
-static void wdt_keepalive(void)
+static int ep93xx_wdt_keepalive(struct watchdog_device *wdd)
 {
        /* user land ping */
        next_heartbeat = jiffies + (timeout * HZ);
-}
-
-static int ep93xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_startup();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
-                loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                               else
-                                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_keepalive();
-       }
 
-       return len;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
-       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
-       .identity = "EP93xx Watchdog",
+static const struct watchdog_info ep93xx_wdt_ident = {
+       .options        = WDIOF_CARDRESET |
+                         WDIOF_MAGICCLOSE |
+                         WDIOF_KEEPALIVEPING,
+       .identity       = "EP93xx Watchdog",
 };
 
-static long ep93xx_wdt_ioctl(struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       int ret = -ENOTTY;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int __user *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int __user *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_keepalive();
-               ret = 0;
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               /* actually, it is 0.250 seconds.... */
-               ret = put_user(1, (int __user *)arg);
-               break;
-       }
-       return ret;
-}
-
-static int ep93xx_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               wdt_shutdown();
-       else
-               printk(KERN_CRIT PFX
-                       "Device closed unexpectedly - timer will not stop\n");
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations ep93xx_wdt_fops = {
+static struct watchdog_ops ep93xx_wdt_ops = {
        .owner          = THIS_MODULE,
-       .write          = ep93xx_wdt_write,
-       .unlocked_ioctl = ep93xx_wdt_ioctl,
-       .open           = ep93xx_wdt_open,
-       .release        = ep93xx_wdt_release,
-       .llseek         = no_llseek,
+       .start          = ep93xx_wdt_start,
+       .stop           = ep93xx_wdt_stop,
+       .ping           = ep93xx_wdt_keepalive,
 };
 
-static struct miscdevice ep93xx_wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &ep93xx_wdt_fops,
+static struct watchdog_device ep93xx_wdt_wdd = {
+       .info           = &ep93xx_wdt_ident,
+       .ops            = &ep93xx_wdt_ops,
 };
 
-static void ep93xx_timer_ping(unsigned long data)
-{
-       if (time_before(jiffies, next_heartbeat))
-               wdt_ping();
-
-       /* Re-set the timer interval */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-}
-
 static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -224,30 +130,35 @@ static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
        if (!mmio_base)
                return -ENXIO;
 
-       err = misc_register(&ep93xx_wdt_miscdev);
-
-       val = readl(mmio_base + EP93XX_WATCHDOG);
-       boot_status = val & 0x01 ? 1 : 0;
-
-       printk(KERN_INFO PFX "EP93XX watchdog, driver version "
-               WDT_VERSION "%s\n",
-               (val & 0x08) ? " (nCS1 disable detected)" : "");
-
        if (timeout < 1 || timeout > 3600) {
                timeout = WDT_TIMEOUT;
-               printk(KERN_INFO PFX
+               dev_warn(&pdev->dev,
                        "timeout value must be 1<=x<=3600, using %d\n",
                        timeout);
        }
 
-       setup_timer(&timer, ep93xx_timer_ping, 1);
-       return err;
+       val = readl(mmio_base + EP93XX_WATCHDOG);
+       ep93xx_wdt_wdd.bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0;
+       ep93xx_wdt_wdd.timeout = timeout;
+
+       watchdog_set_nowayout(&ep93xx_wdt_wdd, nowayout);
+
+       setup_timer(&timer, ep93xx_wdt_timer_ping, 1);
+
+       err = watchdog_register_device(&ep93xx_wdt_wdd);
+       if (err)
+               return err;
+
+       dev_info(&pdev->dev,
+               "EP93XX watchdog, driver version " WDT_VERSION "%s\n",
+               (val & 0x08) ? " (nCS1 disable detected)" : "");
+
+       return 0;
 }
 
 static int __devexit ep93xx_wdt_remove(struct platform_device *pdev)
 {
-       wdt_shutdown();
-       misc_deregister(&ep93xx_wdt_miscdev);
+       watchdog_unregister_device(&ep93xx_wdt_wdd);
        return 0;
 }
 
@@ -262,16 +173,9 @@ static struct platform_driver ep93xx_wdt_driver = {
 
 module_platform_driver(ep93xx_wdt_driver);
 
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,
-       "Watchdog timeout in seconds. (1<=timeout<=3600, default="
-                               __MODULE_STRING(WDT_TIMEOUT) ")");
-
 MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
-               "Alessandro Zummo <a.zummo@towertech.it>");
+               "Alessandro Zummo <a.zummo@towertech.it>,"
+               "H Hartley Sweeten <hsweeten@visionengravers.com>");
 MODULE_DESCRIPTION("EP93xx Watchdog");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(WDT_VERSION);
index 3946c51099c07c6fc211658fd0df5aa51a8970bb..cd31b8a2a729f1a720a61a15a4a7ae3c2ad366ba 100644 (file)
@@ -45,6 +45,8 @@
  *     of the on-board SUPER I/O device SMSC FDC 37B782.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -59,7 +61,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 static unsigned long eurwdt_is_open;
 static int eurwdt_timeout;
@@ -76,8 +77,8 @@ static char *ev = "int";
 
 #define WDT_TIMEOUT            60                /* 1 minute */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -144,11 +145,11 @@ static void eurwdt_activate_timer(void)
 
        /* Setting interrupt line */
        if (irq == 2 || irq > 15 || irq < 0) {
-               printk(KERN_ERR ": invalid irq number\n");
+               pr_err("invalid irq number\n");
                irq = 0;        /* if invalid we disable interrupt */
        }
        if (irq == 0)
-               printk(KERN_INFO ": interrupt disabled\n");
+               pr_info("interrupt disabled\n");
 
        eurwdt_write_reg(WDT_TIMER_CFG, irq << 4);
 
@@ -163,12 +164,12 @@ static void eurwdt_activate_timer(void)
 
 static irqreturn_t eurwdt_interrupt(int irq, void *dev_id)
 {
-       printk(KERN_CRIT "timeout WDT timeout\n");
+       pr_crit("timeout WDT timeout\n");
 
 #ifdef ONLY_TESTING
-       printk(KERN_CRIT "Would Reboot.\n");
+       pr_crit("Would Reboot\n");
 #else
-       printk(KERN_CRIT "Initiating system reboot.\n");
+       pr_crit("Initiating system reboot\n");
        emergency_restart();
 #endif
        return IRQ_HANDLED;
@@ -335,8 +336,7 @@ static int eurwdt_release(struct inode *inode, struct file *file)
        if (eur_expect_close == 42)
                eurwdt_disable_timer();
        else {
-               printk(KERN_CRIT
-                       "eurwdt: Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                eurwdt_ping();
        }
        clear_bit(0, &eurwdt_is_open);
@@ -429,35 +429,32 @@ static int __init eurwdt_init(void)
 
        ret = request_irq(irq, eurwdt_interrupt, 0, "eurwdt", NULL);
        if (ret) {
-               printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
+               pr_err("IRQ %d is not free\n", irq);
                goto out;
        }
 
        if (!request_region(io, 2, "eurwdt")) {
-               printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
+               pr_err("IO %X is not free\n", io);
                ret = -EBUSY;
                goto outirq;
        }
 
        ret = register_reboot_notifier(&eurwdt_notifier);
        if (ret) {
-               printk(KERN_ERR
-                   "eurwdt: can't register reboot notifier (err=%d)\n", ret);
+               pr_err("can't register reboot notifier (err=%d)\n", ret);
                goto outreg;
        }
 
        ret = misc_register(&eurwdt_miscdev);
        if (ret) {
-               printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
-               WATCHDOG_MINOR);
+               pr_err("can't misc_register on minor=%d\n", WATCHDOG_MINOR);
                goto outreboot;
        }
 
        eurwdt_unlock_chip();
 
        ret = 0;
-       printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
-               " - timeout event: %s\n",
+       pr_info("Eurotech WDT driver 0.01 at %X (Interrupt %d) - timeout event: %s\n",
                io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
 
 out:
index e45ca2b4bfbeea2722fb91097fc8f1cfea63d60c..c65b0a5a020c52e6056483a891f793640a4607ff 100644 (file)
@@ -19,6 +19,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -189,8 +191,7 @@ static inline int superio_enter(int base)
 {
        /* Don't step on other drivers' I/O space by accident */
        if (!request_muxed_region(base, 2, DRVNAME)) {
-               printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
-                               (int)base);
+               pr_err("I/O address 0x%04x already in use\n", (int)base);
                return -EBUSY;
        }
 
@@ -217,7 +218,7 @@ static int watchdog_set_timeout(int timeout)
 {
        if (timeout <= 0
         || timeout >  max_timeout) {
-               printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n");
+               pr_err("watchdog timeout out of range\n");
                return -EINVAL;
        }
 
@@ -252,7 +253,7 @@ static int watchdog_set_pulse_width(unsigned int pw)
        } else if (pw <= 5000) {
                watchdog.pulse_val = 3;
        } else {
-               printk(KERN_ERR DRVNAME ": pulse width out of range\n");
+               pr_err("pulse width out of range\n");
                err = -EINVAL;
                goto exit_unlock;
        }
@@ -309,8 +310,7 @@ static int f71862fg_pin_configure(unsigned short ioaddr)
                if (ioaddr)
                        superio_set_bit(ioaddr, SIO_REG_MFUNCT1, 1);
        } else {
-               printk(KERN_ERR DRVNAME ": Invalid argument f71862fg_pin=%d\n",
-                               f71862fg_pin);
+               pr_err("Invalid argument f71862fg_pin=%d\n", f71862fg_pin);
                return -EINVAL;
        }
        return 0;
@@ -487,8 +487,7 @@ static int watchdog_release(struct inode *inode, struct file *file)
 
        if (!watchdog.expect_close) {
                watchdog_keepalive();
-               printk(KERN_CRIT DRVNAME
-                       ": Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
        } else if (!nowayout) {
                watchdog_stop();
        }
@@ -672,25 +671,22 @@ static int __init watchdog_init(int sioaddr)
 
        err = misc_register(&watchdog_miscdev);
        if (err) {
-               printk(KERN_ERR DRVNAME
-                       ": cannot register miscdev on minor=%d\n",
-                               watchdog_miscdev.minor);
+               pr_err("cannot register miscdev on minor=%d\n",
+                      watchdog_miscdev.minor);
                goto exit_reboot;
        }
 
        if (start_withtimeout) {
                if (start_withtimeout <= 0
                 || start_withtimeout >  max_timeout) {
-                       printk(KERN_ERR DRVNAME
-                               ": starting timeout out of range\n");
+                       pr_err("starting timeout out of range\n");
                        err = -EINVAL;
                        goto exit_miscdev;
                }
 
                err = watchdog_start();
                if (err) {
-                       printk(KERN_ERR DRVNAME
-                               ": cannot start watchdog timer\n");
+                       pr_err("cannot start watchdog timer\n");
                        goto exit_miscdev;
                }
 
@@ -720,8 +716,7 @@ static int __init watchdog_init(int sioaddr)
                if (nowayout)
                        __module_get(THIS_MODULE);
 
-               printk(KERN_INFO DRVNAME
-                       ": watchdog started with initial timeout of %u sec\n",
+               pr_info("watchdog started with initial timeout of %u sec\n",
                        start_withtimeout);
        }
 
@@ -746,7 +741,7 @@ static int __init f71808e_find(int sioaddr)
 
        devid = superio_inw(sioaddr, SIO_REG_MANID);
        if (devid != SIO_FINTEK_ID) {
-               pr_debug(DRVNAME ": Not a Fintek device\n");
+               pr_debug("Not a Fintek device\n");
                err = -ENODEV;
                goto exit;
        }
@@ -774,13 +769,13 @@ static int __init f71808e_find(int sioaddr)
                err = -ENODEV;
                goto exit;
        default:
-               printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n",
-                      (unsigned int)devid);
+               pr_info("Unrecognized Fintek device: %04x\n",
+                       (unsigned int)devid);
                err = -ENODEV;
                goto exit;
        }
 
-       printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n",
+       pr_info("Found %s watchdog chip, revision %d\n",
                f71808e_names[watchdog.type],
                (int)superio_inb(sioaddr, SIO_REG_DEVREV));
 exit:
@@ -808,8 +803,7 @@ static int __init f71808e_init(void)
 static void __exit f71808e_exit(void)
 {
        if (watchdog_is_running()) {
-               printk(KERN_WARNING DRVNAME
-                       ": Watchdog timer still running, stopping it\n");
+               pr_warn("Watchdog timer still running, stopping it\n");
                watchdog_stop();
        }
        misc_deregister(&watchdog_miscdev);
index b146082bd85a977410bc240c9bf041f41d63e8b4..17f4cae770c673190a96c996997a4fc06c80285b 100644 (file)
@@ -24,6 +24,8 @@
  * capabilities) a kernel-based watchdog.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/init.h>
@@ -68,8 +70,8 @@ static unsigned int bus_clk;
 static char expect_close;
 static DEFINE_SPINLOCK(gef_wdt_spinlock);
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -110,7 +112,7 @@ static void gef_wdt_handler_enable(void)
        if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_FALSE,
                                   GEF_WDC_ENABLE_SHIFT)) {
                gef_wdt_service();
-               printk(KERN_NOTICE "gef_wdt: watchdog activated\n");
+               pr_notice("watchdog activated\n");
        }
 }
 
@@ -118,7 +120,7 @@ static void gef_wdt_handler_disable(void)
 {
        if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_TRUE,
                                   GEF_WDC_ENABLE_SHIFT))
-               printk(KERN_NOTICE "gef_wdt: watchdog deactivated\n");
+               pr_notice("watchdog deactivated\n");
 }
 
 static void gef_wdt_set_timeout(unsigned int timeout)
@@ -234,8 +236,7 @@ static int gef_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                gef_wdt_handler_disable();
        else {
-               printk(KERN_CRIT
-                      "gef_wdt: unexpected close, not stopping timer!\n");
+               pr_crit("unexpected close, not stopping timer!\n");
                gef_wdt_service();
        }
        expect_close = 0;
@@ -313,7 +314,7 @@ static struct platform_driver gef_wdt_driver = {
 
 static int __init gef_wdt_init(void)
 {
-       printk(KERN_INFO "GE watchdog driver\n");
+       pr_info("GE watchdog driver\n");
        return platform_driver_register(&gef_wdt_driver);
 }
 
index 9b49b125ad5a3a90bfbce7c5bdd07263822dfac8..dc563b680abdf3bb13909be403fd4472cacf5978 100644 (file)
@@ -9,6 +9,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -39,8 +40,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=131, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -100,7 +101,7 @@ static int geodewdt_release(struct inode *inode, struct file *file)
                geodewdt_disable();
                module_put(THIS_MODULE);
        } else {
-               printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n");
+               pr_crit("Unexpected close - watchdog is not stopping\n");
                geodewdt_ping();
 
                set_bit(WDT_FLAGS_ORPHAN, &wdt_flags);
@@ -220,7 +221,7 @@ static int __devinit geodewdt_probe(struct platform_device *dev)
 
        wdt_timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
        if (!wdt_timer) {
-               printk(KERN_ERR "geodewdt:  No timers were available\n");
+               pr_err("No timers were available\n");
                return -ENODEV;
        }
 
index 3c166d3f4e558e4d73ef3ccc333a5678cf7654ee..cbc7ceef2786d418e81a1ed055c8676ad627253f 100644 (file)
@@ -13,6 +13,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -45,7 +47,7 @@
 
 static unsigned int soft_margin = DEFAULT_MARGIN;      /* in seconds */
 static unsigned int reload;                    /* the computed soft_margin */
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static char expect_release;
 static unsigned long hpwdt_is_open;
 
@@ -235,8 +237,7 @@ static int __devinit cru_detect(unsigned long map_entry,
        asminline_call(&cmn_regs, bios32_entrypoint);
 
        if (cmn_regs.u1.ral != 0) {
-               printk(KERN_WARNING
-                       "hpwdt: Call succeeded but with an error: 0x%x\n",
+               pr_warn("Call succeeded but with an error: 0x%x\n",
                        cmn_regs.u1.ral);
        } else {
                physical_bios_base = cmn_regs.u2.rebx;
@@ -256,14 +257,10 @@ static int __devinit cru_detect(unsigned long map_entry,
                        }
                }
 
-               printk(KERN_DEBUG "hpwdt: CRU Base Address:   0x%lx\n",
-                       physical_bios_base);
-               printk(KERN_DEBUG "hpwdt: CRU Offset Address: 0x%lx\n",
-                       physical_bios_offset);
-               printk(KERN_DEBUG "hpwdt: CRU Length:         0x%lx\n",
-                       cru_length);
-               printk(KERN_DEBUG "hpwdt: CRU Mapped Address: %p\n",
-                       &cru_rom_addr);
+               pr_debug("CRU Base Address:   0x%lx\n", physical_bios_base);
+               pr_debug("CRU Offset Address: 0x%lx\n", physical_bios_offset);
+               pr_debug("CRU Length:         0x%lx\n", cru_length);
+               pr_debug("CRU Mapped Address: %p\n", &cru_rom_addr);
        }
        iounmap(bios32_map);
        return retval;
@@ -458,16 +455,13 @@ static void hpwdt_ping(void)
 static int hpwdt_change_timer(int new_margin)
 {
        if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) {
-               printk(KERN_WARNING
-                       "hpwdt: New value passed in is invalid: %d seconds.\n",
+               pr_warn("New value passed in is invalid: %d seconds\n",
                        new_margin);
                return -EINVAL;
        }
 
        soft_margin = new_margin;
-       printk(KERN_DEBUG
-               "hpwdt: New timer passed in is %d seconds.\n",
-               new_margin);
+       pr_debug("New timer passed in is %d seconds\n", new_margin);
        reload = SECS_TO_TICKS(soft_margin);
 
        return 0;
@@ -535,8 +529,7 @@ static int hpwdt_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                hpwdt_stop();
        } else {
-               printk(KERN_CRIT
-                       "hpwdt: Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                hpwdt_ping();
        }
 
@@ -881,7 +874,7 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 module_param(soft_margin, int, 0);
 MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index db45091ef4349c93b039da2efe1deace7e5cf7e3..738032a36bcf013fef05babb92471d9b63ddaafc 100644 (file)
@@ -27,6 +27,8 @@
  *      Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -44,7 +46,6 @@
 #define ESB_VERSION "0.05"
 #define ESB_MODULE_NAME "i6300ESB timer"
 #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
-#define PFX ESB_MODULE_NAME ": "
 
 /* PCI configuration registers */
 #define ESB_CONFIG_REG  0x60            /* Config register                   */
@@ -94,8 +95,8 @@ MODULE_PARM_DESC(heartbeat,
                "Watchdog heartbeat in seconds. (1<heartbeat<2046, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -213,8 +214,7 @@ static int esb_release(struct inode *inode, struct file *file)
        if (esb_expect_close == 42)
                esb_timer_stop();
        else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                esb_timer_keepalive();
        }
        clear_bit(0, &timer_alive);
@@ -347,19 +347,19 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
 static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
 {
        if (pci_enable_device(pdev)) {
-               printk(KERN_ERR PFX "failed to enable device\n");
+               pr_err("failed to enable device\n");
                goto err_devput;
        }
 
        if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) {
-               printk(KERN_ERR PFX "failed to request region\n");
+               pr_err("failed to request region\n");
                goto err_disable;
        }
 
        BASEADDR = pci_ioremap_bar(pdev, 0);
        if (BASEADDR == NULL) {
                /* Something's wrong here, BASEADDR has to be set */
-               printk(KERN_ERR PFX "failed to get BASEADDR\n");
+               pr_err("failed to get BASEADDR\n");
                goto err_release;
        }
 
@@ -397,7 +397,7 @@ static void __devinit esb_initdevice(void)
        /* Check that the WDT isn't already locked */
        pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
        if (val1 & ESB_WDT_LOCK)
-               printk(KERN_WARNING PFX "nowayout already set\n");
+               pr_warn("nowayout already set\n");
 
        /* Set the timer to watchdog mode and disable it for now */
        pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
@@ -423,11 +423,11 @@ static int __devinit esb_probe(struct pci_dev *pdev,
 
        cards_found++;
        if (cards_found == 1)
-               printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
+               pr_info("Intel 6300ESB WatchDog Timer Driver v%s\n",
                        ESB_VERSION);
 
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
@@ -439,9 +439,8 @@ static int __devinit esb_probe(struct pci_dev *pdev,
           if not reset to the default */
        if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) {
                heartbeat = WATCHDOG_HEARTBEAT;
-               printk(KERN_INFO PFX
-                       "heartbeat value must be 1<heartbeat<2046, using %d\n",
-                                                               heartbeat);
+               pr_info("heartbeat value must be 1<heartbeat<2046, using %d\n",
+                       heartbeat);
        }
 
        /* Initialize the watchdog and make sure it does not run */
@@ -450,14 +449,12 @@ static int __devinit esb_probe(struct pci_dev *pdev,
        /* Register the watchdog so that userspace has access to it */
        ret = misc_register(&esb_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto err_unmap;
        }
-       printk(KERN_INFO PFX
-               "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
-                                               BASEADDR, heartbeat, nowayout);
+       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+               BASEADDR, heartbeat, nowayout);
        return 0;
 
 err_unmap:
@@ -503,7 +500,7 @@ static int __init watchdog_init(void)
 static void __exit watchdog_cleanup(void)
 {
        pci_unregister_driver(&esb_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(watchdog_init);
index 481d1ad434640a3c58c1d1a58791f985d75567f5..2721d29ce243fe0d663fea99a4c7823d6bb50277 100644 (file)
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Module and version information */
 #define DRV_NAME       "iTCO_vendor_support"
 #define DRV_VERSION    "1.04"
-#define PFX            DRV_NAME ": "
 
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
@@ -355,13 +356,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
 
 static int __init iTCO_vendor_init_module(void)
 {
-       printk(KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
+       pr_info("vendor-support=%d\n", vendorsupport);
        return 0;
 }
 
 static void __exit iTCO_vendor_exit_module(void)
 {
-       printk(KERN_INFO PFX "Module Unloaded\n");
+       pr_info("Module Unloaded\n");
 }
 
 module_init(iTCO_vendor_init_module);
index bdf401b240b547af6877e00b3286e358eb8f1184..9fecb95645a35d86d5183a27212786abad001fa0 100644 (file)
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Module and version information */
 #define DRV_NAME       "iTCO_wdt"
 #define DRV_VERSION    "1.07"
-#define PFX            DRV_NAME ": "
 
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
@@ -413,8 +414,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
        "5..76 (TCO v1) or 3..614 (TCO v2), default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -489,8 +490,7 @@ static int iTCO_wdt_start(void)
        /* disable chipset's NO_REBOOT bit */
        if (iTCO_wdt_unset_NO_REBOOT_bit()) {
                spin_unlock(&iTCO_wdt_private.io_lock);
-               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
-                                       "reboot disabled by hardware/BIOS\n");
+               pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
                return -EIO;
        }
 
@@ -661,8 +661,7 @@ static int iTCO_wdt_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                iTCO_wdt_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                iTCO_wdt_keepalive();
        }
        clear_bit(0, &is_active);
@@ -804,8 +803,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        base_address &= 0x0000ff80;
        if (base_address == 0x00000000) {
                /* Something's wrong here, ACPIBASE has to be set */
-               printk(KERN_ERR PFX "failed to get TCOBASE address, "
-                                       "device disabled by hardware/BIOS\n");
+               pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n");
                return -ENODEV;
        }
        iTCO_wdt_private.iTCO_version =
@@ -820,8 +818,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        if (iTCO_wdt_private.iTCO_version == 2) {
                pci_read_config_dword(pdev, 0xf0, &base_address);
                if ((base_address & 1) == 0) {
-                       printk(KERN_ERR PFX "RCBA is disabled by hardware"
-                                               "/BIOS, device disabled\n");
+                       pr_err("RCBA is disabled by hardware/BIOS, device disabled\n");
                        ret = -ENODEV;
                        goto out;
                }
@@ -831,8 +828,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
 
        /* Check chipset's NO_REBOOT bit */
        if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
-               printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
-                                       "device disabled by hardware/BIOS\n");
+               pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
                ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
                goto out_unmap;
        }
@@ -842,9 +838,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
 
        /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
        if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
-               printk(KERN_ERR PFX
-                       "I/O address 0x%04lx already in use, "
-                                               "device disabled\n", SMI_EN);
+               pr_err("I/O address 0x%04lx already in use, device disabled\n",
+                      SMI_EN);
                ret = -EIO;
                goto out_unmap;
        }
@@ -858,17 +853,16 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        /* The TCO I/O registers reside in a 32-byte range pointed to
           by the TCOBASE value */
        if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
-               printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
-                                               "device disabled\n", TCOBASE);
+               pr_err("I/O address 0x%04lx already in use, device disabled\n",
+                      TCOBASE);
                ret = -EIO;
                goto unreg_smi_en;
        }
 
-       printk(KERN_INFO PFX
-               "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
-                       iTCO_chipset_info[ent->driver_data].name,
-                       iTCO_chipset_info[ent->driver_data].iTCO_version,
-                       TCOBASE);
+       pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
+               iTCO_chipset_info[ent->driver_data].name,
+               iTCO_chipset_info[ent->driver_data].iTCO_version,
+               TCOBASE);
 
        /* Clear out the (probably old) status */
        outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
@@ -882,20 +876,18 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
           if not reset to the default */
        if (iTCO_wdt_set_heartbeat(heartbeat)) {
                iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                       "timeout value out of range, using %d\n", heartbeat);
+               pr_info("timeout value out of range, using %d\n", heartbeat);
        }
 
        ret = misc_register(&iTCO_wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_region;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-                                                       heartbeat, nowayout);
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
 
        return 0;
 
@@ -947,7 +939,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
        }
 
        if (!found)
-               printk(KERN_INFO PFX "No device detected.\n");
+               pr_info("No device detected\n");
 
        return ret;
 }
@@ -979,8 +971,7 @@ static int __init iTCO_wdt_init_module(void)
 {
        int err;
 
-       printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
-               DRV_VERSION);
+       pr_info("Intel TCO WatchDog Timer Driver v%s\n", DRV_VERSION);
 
        err = platform_driver_register(&iTCO_wdt_driver);
        if (err)
@@ -1004,7 +995,7 @@ static void __exit iTCO_wdt_cleanup_module(void)
 {
        platform_device_unregister(iTCO_wdt_platform_device);
        platform_driver_unregister(&iTCO_wdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(iTCO_wdt_init_module);
index 0149d8dfc81d97c95f4cd1f6f4ace67d56888e07..184c0bfc87a42f5f061e0e316a792260cb67a014 100644 (file)
@@ -31,6 +31,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
@@ -44,7 +46,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 static struct platform_device *ibwdt_platform_device;
 static unsigned long ibwdt_is_open;
@@ -53,7 +54,6 @@ static char expect_close;
 
 /* Module information */
 #define DRV_NAME "ib700wdt"
-#define PFX DRV_NAME ": "
 
 /*
  *
@@ -102,8 +102,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 0<= timeout <=30, default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -246,8 +246,7 @@ static int ibwdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                ibwdt_disable();
        } else {
-               printk(KERN_CRIT PFX
-                    "WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
                ibwdt_ping();
        }
        clear_bit(0, &ibwdt_is_open);
@@ -284,16 +283,14 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
 
 #if WDT_START != WDT_STOP
        if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
-               printk(KERN_ERR PFX "STOP method I/O %X is not available.\n",
-                                                               WDT_STOP);
+               pr_err("STOP method I/O %X is not available\n", WDT_STOP);
                res = -EIO;
                goto out_nostopreg;
        }
 #endif
 
        if (!request_region(WDT_START, 1, "IB700 WDT")) {
-               printk(KERN_ERR PFX "START method I/O %X is not available.\n",
-                                                               WDT_START);
+               pr_err("START method I/O %X is not available\n", WDT_START);
                res = -EIO;
                goto out_nostartreg;
        }
@@ -302,13 +299,12 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
         * if not reset to the default */
        if (ibwdt_set_heartbeat(timeout)) {
                ibwdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be 0<=x<=30, using %d\n", timeout);
+               pr_info("timeout value must be 0<=x<=30, using %d\n", timeout);
        }
 
        res = misc_register(&ibwdt_miscdev);
        if (res) {
-               printk(KERN_ERR PFX "failed to register misc device\n");
+               pr_err("failed to register misc device\n");
                goto out_nomisc;
        }
        return 0;
@@ -353,8 +349,7 @@ static int __init ibwdt_init(void)
 {
        int err;
 
-       printk(KERN_INFO PFX
-               "WDT driver for IB700 single board computer initialising.\n");
+       pr_info("WDT driver for IB700 single board computer initialising\n");
 
        err = platform_driver_register(&ibwdt_driver);
        if (err)
@@ -378,7 +373,7 @@ static void __exit ibwdt_exit(void)
 {
        platform_device_unregister(ibwdt_platform_device);
        platform_driver_unregister(&ibwdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(ibwdt_init);
index c7481ad51629d5b3a47088e0b37466673c2c0afc..bc3fb8fe89abd94312dc0a07e8e19f5e66475c6d 100644 (file)
@@ -10,6 +10,8 @@
  * of the GNU Public License, incorporated herein by reference.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -31,8 +33,6 @@ enum {
        ASMTYPE_SPRUCE,
 };
 
-#define PFX "ibmasr: "
-
 #define TOPAZ_ASR_REG_OFFSET   4
 #define TOPAZ_ASR_TOGGLE       0x40
 #define TOPAZ_ASR_DISABLE      0x80
@@ -60,7 +60,7 @@ enum {
 #define SPRUCE_ASR_TOGGLE_MASK 0x02    /* bit 0: 0, then 1, then 0 */
 
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 static unsigned long asr_is_open;
 static char asr_expect_close;
@@ -234,12 +234,11 @@ static int __init asr_get_base_address(void)
        }
 
        if (!request_region(asr_base, asr_length, "ibmasr")) {
-               printk(KERN_ERR PFX "address %#x already in use\n",
-                       asr_base);
+               pr_err("address %#x already in use\n", asr_base);
                return -EBUSY;
        }
 
-       printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+       pr_info("found %sASR @ addr %#x\n", type, asr_base);
 
        return 0;
 }
@@ -332,8 +331,7 @@ static int asr_release(struct inode *inode, struct file *file)
        if (asr_expect_close == 42)
                asr_disable();
        else {
-               printk(KERN_CRIT PFX
-                               "unexpected close, not stopping watchdog!\n");
+               pr_crit("unexpected close, not stopping watchdog!\n");
                asr_toggle();
        }
        clear_bit(0, &asr_is_open);
@@ -393,7 +391,7 @@ static int __init ibmasr_init(void)
        rc = misc_register(&asr_miscdev);
        if (rc < 0) {
                release_region(asr_base, asr_length);
-               printk(KERN_ERR PFX "failed to register misc device\n");
+               pr_err("failed to register misc device\n");
                return rc;
        }
 
@@ -413,7 +411,7 @@ static void __exit ibmasr_exit(void)
 module_init(ibmasr_init);
 module_exit(ibmasr_exit);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index c44c3334003a11aa3a8cb53e5099c0309c77830f..7a2b734fcdc78f89c3c7f1b9a3eb0f3eb005842c 100644 (file)
@@ -46,6 +46,9 @@
 #define IMX2_WDT_SEQ1          0x5555          /* -> service sequence 1 */
 #define IMX2_WDT_SEQ2          0xAAAA          /* -> service sequence 2 */
 
+#define IMX2_WDT_WRSR          0x04            /* Reset Status Register */
+#define IMX2_WDT_WRSR_TOUT     (1 << 1)        /* -> Reset due to Timeout */
+
 #define IMX2_WDT_MAX_TIME      128
 #define IMX2_WDT_DEFAULT_TIME  60              /* in seconds */
 
@@ -65,8 +68,8 @@ static struct {
 
 static struct miscdevice imx2_wdt_miscdev;
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -175,6 +178,7 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
        void __user *argp = (void __user *)arg;
        int __user *p = argp;
        int new_value;
+       u16 val;
 
        switch (cmd) {
        case WDIOC_GETSUPPORT:
@@ -182,9 +186,13 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
                        sizeof(struct watchdog_info)) ? -EFAULT : 0;
 
        case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
                return put_user(0, p);
 
+       case WDIOC_GETBOOTSTATUS:
+               val = __raw_readw(imx2_wdt.base + IMX2_WDT_WRSR);
+               new_value = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
+               return put_user(new_value, p);
+
        case WDIOC_KEEPALIVE:
                imx2_wdt_ping();
                return 0;
index 1475e09f9af214f5656e6d4ff9b1067555f5554f..6d90f7a2ce2218e36e72282749dd5ab6c1dcbabe 100644 (file)
@@ -12,6 +12,8 @@
  *     based on softdog.c by Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <asm/sgi/mc.h>
 
-#define PFX "indydog: "
 static unsigned long indydog_alive;
 static DEFINE_SPINLOCK(indydog_lock);
 
 #define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -60,7 +61,7 @@ static void indydog_stop(void)
        sgimc->cpuctrl0 = mc_ctrl0;
        spin_unlock(&indydog_lock);
 
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void indydog_ping(void)
@@ -83,7 +84,7 @@ static int indydog_open(struct inode *inode, struct file *file)
        indydog_start();
        indydog_ping();
 
-       printk(KERN_INFO "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 
        return nonseekable_open(inode, file);
 }
@@ -178,30 +179,25 @@ static struct notifier_block indydog_notifier = {
        .notifier_call = indydog_notify_sys,
 };
 
-static char banner[] __initdata =
-       KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
-
 static int __init watchdog_init(void)
 {
        int ret;
 
        ret = register_reboot_notifier(&indydog_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                return ret;
        }
 
        ret = misc_register(&indydog_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&indydog_notifier);
                return ret;
        }
 
-       printk(banner);
+       pr_info("Hardware Watchdog Timer for SGI IP22: 0.3\n");
 
        return 0;
 }
index 1abdc0454c54ff847d3d5159583f396fb2c6baff..9dda2d08af91a23c8ce8cb50d6f1e584212ec597 100644 (file)
@@ -22,6 +22,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -96,15 +98,14 @@ static struct intel_scu_watchdog_dev watchdog_device;
 static void watchdog_fire(void)
 {
        if (force_boot) {
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart();
-               printk(KERN_CRIT PFX "Reboot didn't ?????\n");
+               pr_crit("Reboot didn't ?????\n");
        }
 
        else {
-               printk(KERN_CRIT PFX "Immediate Reboot Disabled\n");
-               printk(KERN_CRIT PFX
-                       "System will reset when watchdog timer times out!\n");
+               pr_crit("Immediate Reboot Disabled\n");
+               pr_crit("System will reset when watchdog timer times out!\n");
        }
 }
 
@@ -112,8 +113,8 @@ static int check_timer_margin(int new_margin)
 {
        if ((new_margin < MIN_TIME_CYCLE) ||
            (new_margin > MAX_TIME - timer_set)) {
-               pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n",
-                         new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
+               pr_debug("value of new_margin %d is out of the range %d to %d\n",
+                        new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
                return -EINVAL;
        }
        return 0;
@@ -156,14 +157,14 @@ static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
        int int_status;
        int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
 
-       pr_debug("Watchdog timer: irq, int_status: %x\n", int_status);
+       pr_debug("irq, int_status: %x\n", int_status);
 
        if (int_status != 0)
                return IRQ_NONE;
 
        /* has the timer been started? If not, then this is spurious */
        if (watchdog_device.timer_started == 0) {
-               pr_debug("Watchdog timer: spurious interrupt received\n");
+               pr_debug("spurious interrupt received\n");
                return IRQ_HANDLED;
        }
 
@@ -220,16 +221,15 @@ static int intel_scu_set_heartbeat(u32 t)
                (watchdog_device.timer_set - timer_margin)
                * watchdog_device.timer_tbl_ptr->freq_hz;
 
-       pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n",
-               watchdog_device.timer_tbl_ptr->freq_hz);
-       pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n",
-               watchdog_device.timer_set);
-       pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n",
-               timer_margin);
-       pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n",
-               watchdog_device.threshold);
-       pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n",
-               watchdog_device.soft_threshold);
+       pr_debug("set_heartbeat: timer freq is %d\n",
+                watchdog_device.timer_tbl_ptr->freq_hz);
+       pr_debug("set_heartbeat: timer_set is %x (hex)\n",
+                watchdog_device.timer_set);
+       pr_debug("set_hearbeat: timer_margin is %x (hex)\n", timer_margin);
+       pr_debug("set_heartbeat: threshold is %x (hex)\n",
+                watchdog_device.threshold);
+       pr_debug("set_heartbeat: soft_threshold is %x (hex)\n",
+                watchdog_device.soft_threshold);
 
        /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
        /* watchdog timing come out right. */
@@ -264,7 +264,7 @@ static int intel_scu_set_heartbeat(u32 t)
 
                if (MAX_RETRY < retry_count++) {
                        /* Unable to set timer value */
-                       pr_err("Watchdog timer: Unable to set timer\n");
+                       pr_err("Unable to set timer\n");
                        return -ENODEV;
                }
 
@@ -321,18 +321,17 @@ static int intel_scu_release(struct inode *inode, struct file *file)
         */
 
        if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
-               pr_debug("Watchdog timer: intel_scu_release, without open\n");
+               pr_debug("intel_scu_release, without open\n");
                return -ENOTTY;
        }
 
        if (!watchdog_device.timer_started) {
                /* Just close, since timer has not been started */
-               pr_debug("Watchdog timer: closed, without starting timer\n");
+               pr_debug("closed, without starting timer\n");
                return 0;
        }
 
-       printk(KERN_CRIT PFX
-              "Unexpected close of /dev/watchdog!\n");
+       pr_crit("Unexpected close of /dev/watchdog!\n");
 
        /* Since the timer was started, prevent future reopens */
        watchdog_device.driver_closed = 1;
@@ -454,9 +453,8 @@ static int __init intel_scu_watchdog_init(void)
        /* Check value of timer_set boot parameter */
        if ((timer_set < MIN_TIME_CYCLE) ||
            (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
-               pr_err("Watchdog timer: value of timer_set %x (hex) "
-                 "is out of range from %x to %x (hex)\n",
-                 timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
+               pr_err("value of timer_set %x (hex) is out of range from %x to %x (hex)\n",
+                      timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
                return -EINVAL;
        }
 
@@ -467,19 +465,18 @@ static int __init intel_scu_watchdog_init(void)
        watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
 
        if (watchdog_device.timer_tbl_ptr == NULL) {
-               pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n");
+               pr_debug("timer is not available\n");
                return -ENODEV;
        }
        /* make sure the timer exists */
        if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
-               pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n",
-                                                               sfi_mtimer_num);
+               pr_debug("timer %d does not have valid physical memory\n",
+                        sfi_mtimer_num);
                return -ENODEV;
        }
 
        if (watchdog_device.timer_tbl_ptr->irq == 0) {
-               pr_debug("Watchdog timer: timer %d invalid irq\n",
-                                                       sfi_mtimer_num);
+               pr_debug("timer %d invalid irq\n", sfi_mtimer_num);
                return -ENODEV;
        }
 
@@ -487,7 +484,7 @@ static int __init intel_scu_watchdog_init(void)
                        20);
 
        if (tmp_addr == NULL) {
-               pr_debug("Watchdog timer: timer unable to ioremap\n");
+               pr_debug("timer unable to ioremap\n");
                return -ENOMEM;
        }
 
@@ -512,7 +509,7 @@ static int __init intel_scu_watchdog_init(void)
 
        ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
        if (ret) {
-               pr_err("Watchdog timer: cannot register notifier %d)\n", ret);
+               pr_err("cannot register notifier %d)\n", ret);
                goto register_reboot_error;
        }
 
@@ -522,8 +519,8 @@ static int __init intel_scu_watchdog_init(void)
 
        ret = misc_register(&watchdog_device.miscdev);
        if (ret) {
-               pr_err("Watchdog timer: cannot register miscdev %d err =%d\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev %d err =%d\n",
+                      WATCHDOG_MINOR, ret);
                goto misc_register_error;
        }
 
@@ -532,7 +529,7 @@ static int __init intel_scu_watchdog_init(void)
                IRQF_SHARED, "watchdog",
                &watchdog_device.timer_load_count_addr);
        if (ret) {
-               pr_err("Watchdog timer: error requesting irq %d\n", ret);
+               pr_err("error requesting irq %d\n", ret);
                goto request_irq_error;
        }
        /* Make sure timer is disabled before returning */
index d2b074a82db69aa6e89a548dc817505450d78932..f3ac608deb6a97fbc97a0af95cf0f2d69a373afb 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef __INTEL_SCU_WATCHDOG_H
 #define __INTEL_SCU_WATCHDOG_H
 
-#define PFX "Intel_SCU: "
 #define WDT_VER "0.3"
 
 /* minimum time between interrupts */
index 82fa7a92a8d280b7f439489dd43ac70e97e5b86d..d964faf1a2505291b15a5e946e4642ef1d292b08 100644 (file)
@@ -24,6 +24,8 @@
  *     Dan Williams <dan.j.williams@intel.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -34,7 +36,7 @@
 #include <linux/uaccess.h>
 #include <mach/hardware.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned long wdt_status;
 static unsigned long boot_status;
 static DEFINE_SPINLOCK(wdt_lock);
@@ -85,7 +87,7 @@ static int wdt_disable(void)
                write_wdtcr(IOP_WDTCR_DIS);
                clear_bit(WDT_ENABLED, &wdt_status);
                spin_unlock(&wdt_lock);
-               printk(KERN_INFO "WATCHDOG: Disabled\n");
+               pr_info("Disabled\n");
                return 0;
        } else
                return 1;
@@ -197,8 +199,8 @@ static int iop_wdt_release(struct inode *inode, struct file *file)
         */
        if (state != 0) {
                wdt_enable();
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                      "reset in %lu seconds\n", iop_watchdog_timeout());
+               pr_crit("Device closed unexpectedly - reset in %lu seconds\n",
+                       iop_watchdog_timeout());
        }
 
        clear_bit(WDT_IN_USE, &wdt_status);
@@ -238,8 +240,7 @@ static int __init iop_wdt_init(void)
           with an open */
        ret = misc_register(&iop_wdt_miscdev);
        if (ret == 0)
-               printk(KERN_INFO "iop watchdog timer: timeout %lu sec\n",
-                      iop_watchdog_timeout());
+               pr_info("timeout %lu sec\n", iop_watchdog_timeout());
 
        return ret;
 }
@@ -252,7 +253,7 @@ static void __exit iop_wdt_exit(void)
 module_init(iop_wdt_init);
 module_exit(iop_wdt_exit);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>");
index 8d2d8502d3e8106c9d4c819b46cfe61715011b5b..f4cce6d66a5573b42afb4517a26752fe15b2a5be 100644 (file)
@@ -20,6 +20,8 @@
  *     software is provided AS-IS with no warranties.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -33,6 +35,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 
+#define DEBUG
 #define NAME "it8712f_wdt"
 
 MODULE_AUTHOR("Jorge Boncompte - DTI2 <jorge@dti2.net>");
@@ -45,8 +48,8 @@ static int margin = 60;               /* in seconds */
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 static unsigned long wdt_open;
@@ -158,10 +161,10 @@ static void it8712f_wdt_update_margin(void)
         */
        if (units <= max_units) {
                config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
-               printk(KERN_INFO NAME ": timer margin %d seconds\n", units);
+               pr_info("timer margin %d seconds\n", units);
        } else {
                units /= 60;
-               printk(KERN_INFO NAME ": timer margin %d minutes\n", units);
+               pr_info("timer margin %d minutes\n", units);
        }
        superio_outb(config, WDT_CONFIG);
 
@@ -184,7 +187,7 @@ static int it8712f_wdt_enable(void)
        if (ret)
                return ret;
 
-       printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
+       pr_debug("enabling watchdog timer\n");
        superio_select(LDN_GPIO);
 
        superio_outb(wdt_control_reg, WDT_CONTROL);
@@ -204,7 +207,7 @@ static int it8712f_wdt_disable(void)
        if (ret)
                return ret;
 
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+       pr_debug("disabling watchdog timer\n");
        superio_select(LDN_GPIO);
 
        superio_outb(0, WDT_CONFIG);
@@ -331,12 +334,10 @@ static int it8712f_wdt_open(struct inode *inode, struct file *file)
 static int it8712f_wdt_release(struct inode *inode, struct file *file)
 {
        if (expect_close != 42) {
-               printk(KERN_WARNING NAME
-                       ": watchdog device closed unexpectedly, will not"
-                       " disable the watchdog timer\n");
+               pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer\n");
        } else if (!nowayout) {
                if (it8712f_wdt_disable())
-                       printk(KERN_WARNING NAME "Watchdog disable failed\n");
+                       pr_warn("Watchdog disable failed\n");
        }
        expect_close = 0;
        clear_bit(0, &wdt_open);
@@ -374,13 +375,13 @@ static int __init it8712f_wdt_find(unsigned short *address)
        superio_select(LDN_GAME);
        superio_outb(1, ACT_REG);
        if (!(superio_inb(ACT_REG) & 0x01)) {
-               printk(KERN_ERR NAME ": Device not activated, skipping\n");
+               pr_err("Device not activated, skipping\n");
                goto exit;
        }
 
        *address = superio_inw(BASE_REG);
        if (*address == 0) {
-               printk(KERN_ERR NAME ": Base address not set, skipping\n");
+               pr_err("Base address not set, skipping\n");
                goto exit;
        }
 
@@ -394,8 +395,7 @@ static int __init it8712f_wdt_find(unsigned short *address)
        if (margin > (max_units * 60))
                margin = (max_units * 60);
 
-       printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - "
-               "using DogFood address 0x%x\n",
+       pr_info("Found IT%04xF chip revision %d - using DogFood address 0x%x\n",
                chip_type, revision, *address);
 
 exit:
@@ -411,27 +411,26 @@ static int __init it8712f_wdt_init(void)
                return -ENODEV;
 
        if (!request_region(address, 1, "IT8712F Watchdog")) {
-               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+               pr_warn("watchdog I/O region busy\n");
                return -EBUSY;
        }
 
        err = it8712f_wdt_disable();
        if (err) {
-               printk(KERN_ERR NAME ": unable to disable watchdog timer.\n");
+               pr_err("unable to disable watchdog timer\n");
                goto out;
        }
 
        err = register_reboot_notifier(&it8712f_wdt_notifier);
        if (err) {
-               printk(KERN_ERR NAME ": unable to register reboot notifier\n");
+               pr_err("unable to register reboot notifier\n");
                goto out;
        }
 
        err = misc_register(&it8712f_wdt_miscdev);
        if (err) {
-               printk(KERN_ERR NAME
-                       ": cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, err);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, err);
                goto reboot_out;
        }
 
index a2d9a1266a23b30e645e4e682bfbabb0b86e2d50..8a741bcb512485194a9f6943baa875bd1d896533 100644 (file)
@@ -29,6 +29,8 @@
  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_VERSION       "1.14"
 #define WATCHDOG_NAME          "IT87 WDT"
-#define PFX                    WATCHDOG_NAME ": "
 #define DRIVER_VERSION         WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
 #define WD_MAGIC               'V'
 
@@ -142,7 +142,7 @@ static      int nogameport = DEFAULT_NOGAMEPORT;
 static int exclusive  = DEFAULT_EXCLUSIVE;
 static int timeout    = DEFAULT_TIMEOUT;
 static int testmode   = DEFAULT_TESTMODE;
-static int nowayout   = DEFAULT_NOWAYOUT;
+static bool nowayout   = DEFAULT_NOWAYOUT;
 
 module_param(nogameport, int, 0);
 MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default="
@@ -156,7 +156,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
 module_param(testmode, int, 0);
 MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
                __MODULE_STRING(DEFAULT_TESTMODE));
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT));
 
@@ -428,8 +428,7 @@ static int wdt_release(struct inode *inode, struct file *file)
                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
                } else {
                        wdt_keepalive();
-                       printk(KERN_CRIT PFX
-                              "unexpected close, not stopping watchdog!\n");
+                       pr_crit("unexpected close, not stopping watchdog!\n");
                }
        }
        clear_bit(WDTS_DEV_OPEN, &wdt_status);
@@ -621,16 +620,14 @@ static int __init it87_wdt_init(void)
                try_gameport = 0;
                break;
        case IT8705_ID:
-               printk(KERN_ERR PFX
-                      "Unsupported Chip found, Chip %04x Revision %02x\n",
+               pr_err("Unsupported Chip found, Chip %04x Revision %02x\n",
                       chip_type, chip_rev);
                return -ENODEV;
        case NO_DEV_ID:
-               printk(KERN_ERR PFX "no device\n");
+               pr_err("no device\n");
                return -ENODEV;
        default:
-               printk(KERN_ERR PFX
-                      "Unknown Chip found, Chip %04x Revision %04x\n",
+               pr_err("Unknown Chip found, Chip %04x Revision %04x\n",
                       chip_type, chip_rev);
                return -ENODEV;
        }
@@ -663,13 +660,11 @@ static int __init it87_wdt_init(void)
        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
                if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
                        if (gp_rreq_fail)
-                               printk(KERN_ERR PFX
-                                       "I/O Address 0x%04x and 0x%04x"
-                                       " already in use\n", base, CIR_BASE);
+                               pr_err("I/O Address 0x%04x and 0x%04x already in use\n",
+                                      base, CIR_BASE);
                        else
-                               printk(KERN_ERR PFX
-                                       "I/O Address 0x%04x already in use\n",
-                                       CIR_BASE);
+                               pr_err("I/O Address 0x%04x already in use\n",
+                                      CIR_BASE);
                        rc = -EIO;
                        goto err_out;
                }
@@ -688,9 +683,8 @@ static int __init it87_wdt_init(void)
 
        if (timeout < 1 || timeout > max_units * 60) {
                timeout = DEFAULT_TIMEOUT;
-               printk(KERN_WARNING PFX
-                      "Timeout value out of range, use default %d sec\n",
-                      DEFAULT_TIMEOUT);
+               pr_warn("Timeout value out of range, use default %d sec\n",
+                       DEFAULT_TIMEOUT);
        }
 
        if (timeout > max_units)
@@ -698,16 +692,14 @@ static int __init it87_wdt_init(void)
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                      "Cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("Cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                      "Cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
+               pr_err("Cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
@@ -722,9 +714,8 @@ static int __init it87_wdt_init(void)
                outb(0x09, CIR_IER(base));
        }
 
-       printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
-               "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
-               "nogameport=%d)\n", chip_type, chip_rev, timeout,
+       pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d exclusive=%d nogameport=%d)\n",
+               chip_type, chip_rev, timeout,
                nowayout, testmode, exclusive, nogameport);
 
        superio_exit();
index 084f71aa855a7a7599359d081ca30478386998ef..3f047a58d3aecf41235a1a5f9e622a0347b68061 100644 (file)
@@ -16,6 +16,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 #include <linux/uaccess.h>
 #include <mach/hardware.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int heartbeat = 60;    /* (secs) Default is 1 minute */
 static unsigned long wdt_status;
 static DEFINE_SPINLOCK(wdt_lock);
@@ -158,8 +160,7 @@ static int ixp2000_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                wdt_disable();
        else
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
        clear_bit(WDT_IN_USE, &wdt_status);
        clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
 
@@ -185,7 +186,7 @@ static struct miscdevice ixp2000_wdt_miscdev = {
 static int __init ixp2000_wdt_init(void)
 {
        if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
-               printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+               pr_info("Unable to use IXP2000 watchdog due to IXP2800 erratum #25\n");
                return -EIO;
        }
        wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
@@ -206,7 +207,7 @@ MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index 4fc2e9ac26f7c818768c0e6f1a05a78b789cd7e7..5580b4fff7fe0dc7fd85376e3313678356cc650f 100644 (file)
@@ -13,6 +13,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -25,7 +27,7 @@
 #include <linux/uaccess.h>
 #include <mach/hardware.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = 60;     /* (secs) Default is 1 minute */
 static unsigned long wdt_status;
 static unsigned long boot_status;
@@ -147,8 +149,7 @@ static int ixp4xx_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                wdt_disable();
        else
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
        clear_bit(WDT_IN_USE, &wdt_status);
        clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
 
@@ -176,8 +177,7 @@ static int __init ixp4xx_wdt_init(void)
        int ret;
 
        if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
-               printk(KERN_ERR "IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected"
-                       " - watchdog disabled\n");
+               pr_err("Rev. A0 IXP42x CPU detected - watchdog disabled\n");
 
                return -ENODEV;
        }
@@ -185,8 +185,7 @@ static int __init ixp4xx_wdt_init(void)
                        WDIOF_CARDRESET : 0;
        ret = misc_register(&ixp4xx_wdt_miscdev);
        if (ret == 0)
-               printk(KERN_INFO "IXP4xx Watchdog Timer: heartbeat %d sec\n",
-                       heartbeat);
+               pr_info("timer heartbeat %d sec\n", heartbeat);
        return ret;
 }
 
@@ -205,7 +204,7 @@ MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index 17ef300bccc52ca6e8c78edd1f0cc391f2504147..978615ef899d5e52dfb403dd583762fa5cd5fbae 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #include <asm/mach-jz4740/timer.h>
 
@@ -41,9 +38,6 @@
 #define JZ_WDT_CLOCK_RTC  0x2
 #define JZ_WDT_CLOCK_EXT  0x4
 
-#define WDT_IN_USE        0
-#define WDT_OK_TO_CLOSE   1
-
 #define JZ_WDT_CLOCK_DIV_SHIFT   3
 
 #define JZ_WDT_CLOCK_DIV_1    (0 << JZ_WDT_CLOCK_DIV_SHIFT)
 #define DEFAULT_HEARTBEAT 5
 #define MAX_HEARTBEAT     2048
 
-static struct {
-       void __iomem *base;
-       struct resource *mem;
-       struct clk *rtc_clk;
-       unsigned long status;
-} jz4740_wdt;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static int heartbeat = DEFAULT_HEARTBEAT;
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0);
+MODULE_PARM_DESC(heartbeat,
+               "Watchdog heartbeat period in seconds from 1 to "
+               __MODULE_STRING(MAX_HEARTBEAT) ", default "
+               __MODULE_STRING(DEFAULT_HEARTBEAT));
 
+struct jz4740_wdt_drvdata {
+       struct watchdog_device wdt;
+       void __iomem *base;
+       struct clk *rtc_clk;
+};
 
-static void jz4740_wdt_service(void)
+static int jz4740_wdt_ping(struct watchdog_device *wdt_dev)
 {
-       writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
+       struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+       writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
+       return 0;
 }
 
-static void jz4740_wdt_set_heartbeat(int new_heartbeat)
+static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                   unsigned int new_timeout)
 {
+       struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
        unsigned int rtc_clk_rate;
        unsigned int timeout_value;
        unsigned short clock_div = JZ_WDT_CLOCK_DIV_1;
 
-       heartbeat = new_heartbeat;
-
-       rtc_clk_rate = clk_get_rate(jz4740_wdt.rtc_clk);
+       rtc_clk_rate = clk_get_rate(drvdata->rtc_clk);
 
-       timeout_value = rtc_clk_rate * heartbeat;
+       timeout_value = rtc_clk_rate * new_timeout;
        while (timeout_value > 0xffff) {
                if (clock_div == JZ_WDT_CLOCK_DIV_1024) {
                        /* Requested timeout too high;
@@ -93,199 +99,115 @@ static void jz4740_wdt_set_heartbeat(int new_heartbeat)
                clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT);
        }
 
-       writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
-       writew(clock_div, jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
+       writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+       writew(clock_div, drvdata->base + JZ_REG_WDT_TIMER_CONTROL);
 
-       writew((u16)timeout_value, jz4740_wdt.base + JZ_REG_WDT_TIMER_DATA);
-       writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
+       writew((u16)timeout_value, drvdata->base + JZ_REG_WDT_TIMER_DATA);
+       writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
        writew(clock_div | JZ_WDT_CLOCK_RTC,
-               jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
+               drvdata->base + JZ_REG_WDT_TIMER_CONTROL);
 
-       writeb(0x1, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
-}
+       writeb(0x1, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
 
-static void jz4740_wdt_enable(void)
-{
-       jz4740_timer_enable_watchdog();
-       jz4740_wdt_set_heartbeat(heartbeat);
-}
-
-static void jz4740_wdt_disable(void)
-{
-       jz4740_timer_disable_watchdog();
-       writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
+       wdt_dev->timeout = new_timeout;
+       return 0;
 }
 
-static int jz4740_wdt_open(struct inode *inode, struct file *file)
+static int jz4740_wdt_start(struct watchdog_device *wdt_dev)
 {
-       if (test_and_set_bit(WDT_IN_USE, &jz4740_wdt.status))
-               return -EBUSY;
-
-       jz4740_wdt_enable();
+       jz4740_timer_enable_watchdog();
+       jz4740_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
 
-       return nonseekable_open(inode, file);
+       return 0;
 }
 
-static ssize_t jz4740_wdt_write(struct file *file, const char *data,
-               size_t len, loff_t *ppos)
+static int jz4740_wdt_stop(struct watchdog_device *wdt_dev)
 {
-       if (len) {
-               size_t i;
-
-               clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
-               for (i = 0; i != len; i++) {
-                       char c;
+       struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
 
-                       if (get_user(c, data + i))
-                               return -EFAULT;
-
-                       if (c == 'V')
-                               set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
-               }
-               jz4740_wdt_service();
-       }
+       jz4740_timer_disable_watchdog();
+       writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
 
-       return len;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
-       .options = WDIOF_KEEPALIVEPING,
+static const struct watchdog_info jz4740_wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "jz4740 Watchdog",
 };
 
-static long jz4740_wdt_ioctl(struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int heartbeat_seconds;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               jz4740_wdt_service();
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(heartbeat_seconds, (int __user *)arg))
-                       return -EFAULT;
-
-               jz4740_wdt_set_heartbeat(heartbeat_seconds);
-               return 0;
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(heartbeat, (int *)arg);
-
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-static int jz4740_wdt_release(struct inode *inode, struct file *file)
-{
-       jz4740_wdt_service();
-
-       if (test_and_clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status))
-               jz4740_wdt_disable();
-
-       clear_bit(WDT_IN_USE, &jz4740_wdt.status);
-       return 0;
-}
-
-static const struct file_operations jz4740_wdt_fops = {
+static const struct watchdog_ops jz4740_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = jz4740_wdt_write,
-       .unlocked_ioctl = jz4740_wdt_ioctl,
-       .open = jz4740_wdt_open,
-       .release = jz4740_wdt_release,
-};
-
-static struct miscdevice jz4740_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &jz4740_wdt_fops,
+       .start = jz4740_wdt_start,
+       .stop = jz4740_wdt_stop,
+       .ping = jz4740_wdt_ping,
+       .set_timeout = jz4740_wdt_set_timeout,
 };
 
 static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
 {
-       int ret = 0, size;
-       struct resource *res;
-       struct device *dev = &pdev->dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(dev, "failed to get memory region resource\n");
-               return -ENXIO;
+       struct jz4740_wdt_drvdata *drvdata;
+       struct watchdog_device *jz4740_wdt;
+       struct resource *res;
+       int ret;
+
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct jz4740_wdt_drvdata),
+                              GFP_KERNEL);
+       if (!drvdata) {
+               dev_err(&pdev->dev, "Unable to alloacate watchdog device\n");
+               return -ENOMEM;
        }
 
-       size = resource_size(res);
-       jz4740_wdt.mem = request_mem_region(res->start, size, pdev->name);
-       if (jz4740_wdt.mem == NULL) {
-               dev_err(dev, "failed to get memory region\n");
-               return -EBUSY;
-       }
+       if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
+               heartbeat = DEFAULT_HEARTBEAT;
 
-       jz4740_wdt.base = ioremap_nocache(res->start, size);
-       if (jz4740_wdt.base == NULL) {
-               dev_err(dev, "failed to map memory region\n");
+       jz4740_wdt = &drvdata->wdt;
+       jz4740_wdt->info = &jz4740_wdt_info;
+       jz4740_wdt->ops = &jz4740_wdt_ops;
+       jz4740_wdt->timeout = heartbeat;
+       jz4740_wdt->min_timeout = 1;
+       jz4740_wdt->max_timeout = MAX_HEARTBEAT;
+       watchdog_set_nowayout(jz4740_wdt, nowayout);
+       watchdog_set_drvdata(jz4740_wdt, drvdata);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       drvdata->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (drvdata->base == NULL) {
                ret = -EBUSY;
-               goto err_release_region;
+               goto err_out;
        }
 
-       jz4740_wdt.rtc_clk = clk_get(NULL, "rtc");
-       if (IS_ERR(jz4740_wdt.rtc_clk)) {
-               dev_err(dev, "cannot find RTC clock\n");
-               ret = PTR_ERR(jz4740_wdt.rtc_clk);
-               goto err_iounmap;
+       drvdata->rtc_clk = clk_get(NULL, "rtc");
+       if (IS_ERR(drvdata->rtc_clk)) {
+               dev_err(&pdev->dev, "cannot find RTC clock\n");
+               ret = PTR_ERR(drvdata->rtc_clk);
+               goto err_out;
        }
 
-       ret = misc_register(&jz4740_wdt_miscdev);
-       if (ret < 0) {
-               dev_err(dev, "cannot register misc device\n");
+       ret = watchdog_register_device(&drvdata->wdt);
+       if (ret < 0)
                goto err_disable_clk;
-       }
 
+       platform_set_drvdata(pdev, drvdata);
        return 0;
 
 err_disable_clk:
-       clk_put(jz4740_wdt.rtc_clk);
-err_iounmap:
-       iounmap(jz4740_wdt.base);
-err_release_region:
-       release_mem_region(jz4740_wdt.mem->start,
-                       resource_size(jz4740_wdt.mem));
+       clk_put(drvdata->rtc_clk);
+err_out:
        return ret;
 }
 
-
 static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
 {
-       jz4740_wdt_disable();
-       misc_deregister(&jz4740_wdt_miscdev);
-       clk_put(jz4740_wdt.rtc_clk);
+       struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
 
-       iounmap(jz4740_wdt.base);
-       jz4740_wdt.base = NULL;
-
-       release_mem_region(jz4740_wdt.mem->start,
-                               resource_size(jz4740_wdt.mem));
-       jz4740_wdt.mem = NULL;
+       jz4740_wdt_stop(&drvdata->wdt);
+       watchdog_unregister_device(&drvdata->wdt);
+       clk_put(drvdata->rtc_clk);
 
        return 0;
 }
 
-
 static struct platform_driver jz4740_wdt_driver = {
        .probe = jz4740_wdt_probe,
        .remove = __devexit_p(jz4740_wdt_remove),
@@ -299,13 +221,6 @@ module_platform_driver(jz4740_wdt_driver);
 
 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
 MODULE_DESCRIPTION("jz4740 Watchdog Driver");
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat,
-               "Watchdog heartbeat period in seconds from 1 to "
-               __MODULE_STRING(MAX_HEARTBEAT) ", default "
-               __MODULE_STRING(DEFAULT_HEARTBEAT));
-
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS("platform:jz4740-wdt");
index 51757a520e8f07d96f8e247b960eda886fda8528..59e75d9a6b7fc2a59513e3cc066cf1b3443649da 100644 (file)
@@ -8,6 +8,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #define WDT_MAX_TIME           171     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
                                        __MODULE_STRING(WDT_DEFAULT_TIME) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 #endif
@@ -233,8 +235,8 @@ static int __devinit ks8695wdt_probe(struct platform_device *pdev)
        if (res)
                return res;
 
-       printk(KERN_INFO "KS8695 Watchdog Timer enabled (%d seconds%s)\n",
-                               wdt_time, nowayout ? ", nowayout" : "");
+       pr_info("KS8695 Watchdog Timer enabled (%d seconds%s)\n",
+               wdt_time, nowayout ? ", nowayout" : "");
        return 0;
 }
 
index d3a63be2e28d07974249b082749781dbc46df2f1..a9593a3a32a09a1c44d367877d5feb9486efb609 100644 (file)
@@ -7,6 +7,8 @@
  *  Based on EP93xx wdt driver
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
@@ -38,7 +40,7 @@
 #define LTQ_WDT_DIVIDER                0x40000
 #define LTQ_MAX_TIMEOUT                ((1 << 16) - 1) /* the reload field is 16 bit */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 static void __iomem *ltq_wdt_membase;
 static unsigned long ltq_io_region_clk_rate;
@@ -160,7 +162,7 @@ ltq_wdt_release(struct inode *inode, struct file *file)
        if (ltq_wdt_ok_to_close)
                ltq_wdt_disable();
        else
-               pr_err("ltq_wdt: watchdog closed without warning\n");
+               pr_err("watchdog closed without warning\n");
        ltq_wdt_ok_to_close = 0;
        clear_bit(0, &ltq_wdt_in_use);
 
@@ -249,7 +251,7 @@ exit_ltq_wdt(void)
 module_init(init_ltq_wdt);
 module_exit(exit_ltq_wdt);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
index 4d43286074aa16d656ad4bbad1d00874ccaed769..663cad86c6333c29855a2a209fed47465437d238 100644 (file)
@@ -16,6 +16,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -32,7 +34,7 @@
 #include <asm/m54xxsim.h>
 #include <asm/m54xxgpt.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int heartbeat = 30;    /* (secs) Default is 0.5 minute */
 static unsigned long wdt_status;
 
@@ -166,8 +168,7 @@ static int m54xx_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                wdt_disable();
        else {
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
                wdt_keepalive();
        }
        clear_bit(WDT_IN_USE, &wdt_status);
@@ -196,11 +197,10 @@ static int __init m54xx_wdt_init(void)
 {
        if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4,
                                                "Coldfire M54xx Watchdog")) {
-               printk(KERN_WARNING
-                               "Coldfire M54xx Watchdog : I/O region busy\n");
+               pr_warn("I/O region busy\n");
                return -EBUSY;
        }
-       printk(KERN_INFO "ColdFire watchdog driver is loaded.\n");
+       pr_info("driver is loaded\n");
 
        return misc_register(&m54xx_wdt_miscdev);
 }
@@ -220,7 +220,7 @@ MODULE_DESCRIPTION("Coldfire M54xx Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index 1332b838cc5830f0be76fe104abdcf8c4e40cd93..bf84f788e59261f985ce85dce2a6fade949807e9 100644 (file)
@@ -28,6 +28,8 @@
  *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -43,7 +45,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 /* ports */
 #define ZF_IOBASE      0x218
@@ -93,8 +94,8 @@ MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -141,10 +142,10 @@ static unsigned long next_heartbeat;
 #define ZF_CTIMEOUT 0xffff
 
 #ifndef ZF_DEBUG
-#      define dprintk(format, args...)
+#define dprintk(format, args...)
 #else
-#      define dprintk(format, args...) printk(KERN_DEBUG PFX \
-                               ":%s:%d: " format, __func__, __LINE__ , ## args)
+#define dprintk(format, args...)                                       \
+       pr_debug(":%s:%d: " format, __func__, __LINE__ , ## args)
 #endif
 
 
@@ -203,7 +204,7 @@ static void zf_timer_off(void)
        zf_set_control(ctrl_reg);
        spin_unlock_irqrestore(&zf_port_lock, flags);
 
-       printk(KERN_INFO PFX ": Watchdog timer is now disabled\n");
+       pr_info("Watchdog timer is now disabled\n");
 }
 
 
@@ -233,7 +234,7 @@ static void zf_timer_on(void)
        zf_set_control(ctrl_reg);
        spin_unlock_irqrestore(&zf_port_lock, flags);
 
-       printk(KERN_INFO PFX ": Watchdog timer is now enabled\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 
@@ -263,7 +264,7 @@ static void zf_ping(unsigned long data)
 
                mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
        } else
-               printk(KERN_CRIT PFX ": I will reset your machine\n");
+               pr_crit("I will reset your machine\n");
 }
 
 static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
@@ -342,8 +343,7 @@ static int zf_close(struct inode *inode, struct file *file)
                zf_timer_off();
        else {
                del_timer(&zf_timer);
-               printk(KERN_ERR PFX ": device file closed unexpectedly. "
-                                               "Will not stop the WDT!\n");
+               pr_err("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &zf_is_open);
        zf_expect_close = 0;
@@ -390,19 +390,18 @@ static void __init zf_show_action(int act)
 {
        static const char * const str[] = { "RESET", "SMI", "NMI", "SCI" };
 
-       printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
+       pr_info("Watchdog using action = %s\n", str[act]);
 }
 
 static int __init zf_init(void)
 {
        int ret;
 
-       printk(KERN_INFO PFX
-               ": MachZ ZF-Logic Watchdog driver initializing.\n");
+       pr_info("MachZ ZF-Logic Watchdog driver initializing\n");
 
        ret = zf_get_ZFL_version();
        if (!ret || ret == 0xffff) {
-               printk(KERN_WARNING PFX ": no ZF-Logic found\n");
+               pr_warn("no ZF-Logic found\n");
                return -ENODEV;
        }
 
@@ -414,23 +413,20 @@ static int __init zf_init(void)
        zf_show_action(action);
 
        if (!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")) {
-               printk(KERN_ERR "cannot reserve I/O ports at %d\n",
-                                                       ZF_IOBASE);
+               pr_err("cannot reserve I/O ports at %d\n", ZF_IOBASE);
                ret = -EBUSY;
                goto no_region;
        }
 
        ret = register_reboot_notifier(&zf_notifier);
        if (ret) {
-               printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
-                                                                       ret);
+               pr_err("can't register reboot notifier (err=%d)\n", ret);
                goto no_reboot;
        }
 
        ret = misc_register(&zf_miscdev);
        if (ret) {
-               printk(KERN_ERR "can't misc_register on minor=%d\n",
-                                                       WATCHDOG_MINOR);
+               pr_err("can't misc_register on minor=%d\n", WATCHDOG_MINOR);
                goto no_misc;
        }
 
index af63ecfbfa6f4c132082f856d7fd80d0d7d61ae5..8f4a74e91619fd693c651e7c391538a169a3dd23 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
-#include <linux/device.h>
 #include <linux/slab.h>
 
 #define DEFAULT_HEARTBEAT 60
 #define MAX_HEARTBEAT     60
 
-static int heartbeat = DEFAULT_HEARTBEAT;
-static int nowayout  = WATCHDOG_NOWAYOUT;
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+static bool nowayout  = WATCHDOG_NOWAYOUT;
 
 /*
  * Memory mapping: a single byte, 3 first lower bits to select bit 3
@@ -45,15 +42,8 @@ static int nowayout  = WATCHDOG_NOWAYOUT;
 
 static DEFINE_SPINLOCK(io_lock);
 
-static unsigned long wdt_status;
-#define WDT_IN_USE     0
-#define WDT_RUNNING    1
-#define WDT_OK_TO_CLOSE 2
-
 static int nodelay;
-static struct resource *wdt_mem;
 static void __iomem    *wdt_base;
-static struct platform_device *max63xx_pdev;
 
 /*
  * The timeout values used are actually the absolute minimum the chip
@@ -117,7 +107,7 @@ max63xx_select_timeout(struct max63xx_timeout *table, int value)
        return NULL;
 }
 
-static void max63xx_wdt_ping(void)
+static int max63xx_wdt_ping(struct watchdog_device *wdd)
 {
        u8 val;
 
@@ -129,15 +119,14 @@ static void max63xx_wdt_ping(void)
        __raw_writeb(val & ~MAX6369_WDI, wdt_base);
 
        spin_unlock(&io_lock);
+       return 0;
 }
 
-static void max63xx_wdt_enable(struct max63xx_timeout *entry)
+static int max63xx_wdt_start(struct watchdog_device *wdd)
 {
+       struct max63xx_timeout *entry = watchdog_get_drvdata(wdd);
        u8 val;
 
-       if (test_and_set_bit(WDT_RUNNING, &wdt_status))
-               return;
-
        spin_lock(&io_lock);
 
        val = __raw_readb(wdt_base);
@@ -149,10 +138,11 @@ static void max63xx_wdt_enable(struct max63xx_timeout *entry)
 
        /* check for a edge triggered startup */
        if (entry->tdelay == 0)
-               max63xx_wdt_ping();
+               max63xx_wdt_ping(wdd);
+       return 0;
 }
 
-static void max63xx_wdt_disable(void)
+static int max63xx_wdt_stop(struct watchdog_device *wdd)
 {
        u8 val;
 
@@ -164,113 +154,29 @@ static void max63xx_wdt_disable(void)
        __raw_writeb(val, wdt_base);
 
        spin_unlock(&io_lock);
-
-       clear_bit(WDT_RUNNING, &wdt_status);
-}
-
-static int max63xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       max63xx_wdt_enable(current_timeout);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t max63xx_wdt_write(struct file *file, const char *data,
-                                size_t len, loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-
-               max63xx_wdt_ping();
-       }
-
-       return len;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
-       .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+static const struct watchdog_info max63xx_wdt_info = {
+       .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "max63xx Watchdog",
 };
 
-static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       int ret = -ENOTTY;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               max63xx_wdt_ping();
-               ret = 0;
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-       }
-       return ret;
-}
-
-static int max63xx_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               max63xx_wdt_disable();
-       else
-               dev_crit(&max63xx_pdev->dev,
-                        "device closed unexpectedly - timer will not stop\n");
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations max63xx_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = max63xx_wdt_write,
-       .unlocked_ioctl = max63xx_wdt_ioctl,
-       .open           = max63xx_wdt_open,
-       .release        = max63xx_wdt_release,
+static const struct watchdog_ops max63xx_wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = max63xx_wdt_start,
+       .stop = max63xx_wdt_stop,
+       .ping = max63xx_wdt_ping,
 };
 
-static struct miscdevice max63xx_wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &max63xx_wdt_fops,
+static struct watchdog_device max63xx_wdt_dev = {
+       .info = &max63xx_wdt_info,
+       .ops = &max63xx_wdt_ops,
 };
 
 static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
 {
-       int ret = 0;
-       int size;
-       struct device *dev = &pdev->dev;
+       struct resource *wdt_mem;
        struct max63xx_timeout *table;
 
        table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
@@ -278,68 +184,34 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
 
-       dev_info(dev, "requesting %ds heartbeat\n", heartbeat);
+       dev_info(&pdev->dev, "requesting %ds heartbeat\n", heartbeat);
        current_timeout = max63xx_select_timeout(table, heartbeat);
 
        if (!current_timeout) {
-               dev_err(dev, "unable to satisfy heartbeat request\n");
+               dev_err(&pdev->dev, "unable to satisfy heartbeat request\n");
                return -EINVAL;
        }
 
-       dev_info(dev, "using %ds heartbeat with %ds initial delay\n",
+       dev_info(&pdev->dev, "using %ds heartbeat with %ds initial delay\n",
                 current_timeout->twd, current_timeout->tdelay);
 
        heartbeat = current_timeout->twd;
 
-       max63xx_pdev = pdev;
-
        wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (wdt_mem == NULL) {
-               dev_err(dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
+       wdt_base = devm_request_and_ioremap(&pdev->dev, wdt_mem);
+       if (!wdt_base)
+               return -ENOMEM;
 
-       size = resource_size(wdt_mem);
-       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
-               dev_err(dev, "failed to get memory region\n");
-               return -ENOENT;
-       }
-
-       wdt_base = ioremap(wdt_mem->start, size);
-       if (!wdt_base) {
-               dev_err(dev, "failed to map memory region\n");
-               ret = -ENOMEM;
-               goto out_request;
-       }
+       max63xx_wdt_dev.timeout = heartbeat;
+       watchdog_set_nowayout(&max63xx_wdt_dev, nowayout);
+       watchdog_set_drvdata(&max63xx_wdt_dev, current_timeout);
 
-       ret = misc_register(&max63xx_wdt_miscdev);
-       if (ret < 0) {
-               dev_err(dev, "cannot register misc device\n");
-               goto out_unmap;
-       }
-
-       return 0;
-
-out_unmap:
-       iounmap(wdt_base);
-out_request:
-       release_mem_region(wdt_mem->start, size);
-       wdt_mem = NULL;
-
-       return ret;
+       return watchdog_register_device(&max63xx_wdt_dev);
 }
 
 static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
 {
-       misc_deregister(&max63xx_wdt_miscdev);
-       if (wdt_mem) {
-               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
-               wdt_mem = NULL;
-       }
-
-       if (wdt_base)
-               iounmap(wdt_base);
-
+       watchdog_unregister_device(&max63xx_wdt_dev);
        return 0;
 }
 
@@ -375,7 +247,7 @@ MODULE_PARM_DESC(heartbeat,
                 __MODULE_STRING(MAX_HEARTBEAT) ", default "
                 __MODULE_STRING(DEFAULT_HEARTBEAT));
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index bc820d16699ab1df0f6ede8d55f052c5f2236043..37e4b52dbce982c6bb64a39601b7cfd7e164d82c 100644 (file)
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define VERSION "0.6"
 #define WATCHDOG_NAME "mixcomwd"
-#define PFX WATCHDOG_NAME ": "
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -107,8 +108,8 @@ static int mixcomwd_timer_alive;
 static DEFINE_TIMER(mixcomwd_timer, mixcomwd_timerfun, 0, 0);
 static char expect_close;
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -156,15 +157,13 @@ static int mixcomwd_release(struct inode *inode, struct file *file)
 {
        if (expect_close == 42) {
                if (mixcomwd_timer_alive) {
-                       printk(KERN_ERR PFX
-                               "release called while internal timer alive");
+                       pr_err("release called while internal timer alive\n");
                        return -EBUSY;
                }
                mixcomwd_timer_alive = 1;
                mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
        } else
-               printk(KERN_CRIT PFX
-                   "WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
 
        clear_bit(0, &mixcomwd_opened);
        expect_close = 0;
@@ -274,22 +273,19 @@ static int __init mixcomwd_init(void)
        }
 
        if (!found) {
-               printk(KERN_ERR PFX
-                       "No card detected, or port not available.\n");
+               pr_err("No card detected, or port not available\n");
                return -ENODEV;
        }
 
        ret = misc_register(&mixcomwd_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto error_misc_register_watchdog;
        }
 
-       printk(KERN_INFO
-               "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
-                                       VERSION, watchdog_port);
+       pr_info("MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
+               VERSION, watchdog_port);
 
        return 0;
 
@@ -303,8 +299,7 @@ static void __exit mixcomwd_exit(void)
 {
        if (!nowayout) {
                if (mixcomwd_timer_alive) {
-                       printk(KERN_WARNING PFX "I quit now, hardware will"
-                              " probably reboot!\n");
+                       pr_warn("I quit now, hardware will probably reboot!\n");
                        del_timer_sync(&mixcomwd_timer);
                        mixcomwd_timer_alive = 0;
                }
index 20feb4d3d791037049bbd95b9b0d8c93874f8af6..40f7bf1f8654da6f9db51a1d78637353f55cd9f3 100644 (file)
@@ -17,6 +17,8 @@
  * option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -60,8 +62,8 @@ module_param(reset, bool, 0);
 MODULE_PARM_DESC(reset,
        "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -96,7 +98,7 @@ static void mpc8xxx_wdt_timer_ping(unsigned long arg)
 
 static void mpc8xxx_wdt_pr_warn(const char *msg)
 {
-       pr_crit("mpc8xxx_wdt: %s, expect the %s soon!\n", msg,
+       pr_crit("%s, expect the %s soon!\n", msg,
                reset ? "reset" : "machine check exception");
 }
 
@@ -209,7 +211,7 @@ static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
 
        enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN;
        if (!enabled && wdt_type->hw_enabled) {
-               pr_info("mpc8xxx_wdt: could not be enabled in software\n");
+               pr_info("could not be enabled in software\n");
                ret = -ENOSYS;
                goto err_unmap;
        }
@@ -226,9 +228,8 @@ static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
                goto err_unmap;
 #endif
 
-       pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d "
-               "(%d seconds)\n", reset ? "reset" : "interrupt", timeout,
-               timeout_sec);
+       pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d (%d seconds)\n",
+               reset ? "reset" : "interrupt", timeout, timeout_sec);
 
        /*
         * If the watchdog was previously enabled or we're running on
@@ -303,7 +304,7 @@ static int mpc8xxx_wdt_init_late(void)
        ret = misc_register(&mpc8xxx_wdt_miscdev);
        if (ret) {
                pr_err("cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+                      WATCHDOG_MINOR, ret);
                return ret;
        }
        return 0;
index 82ccd36e2c901489aa911c5f2dab68d29729fcfc..7c741dc987bd5058904dc03502bf169512db4db2 100644 (file)
@@ -19,6 +19,9 @@
  *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -44,7 +47,7 @@ struct mpcore_wdt {
        char            expect_close;
 };
 
-static struct platform_device *mpcore_wdt_dev;
+static struct platform_device *mpcore_wdt_pdev;
 static DEFINE_SPINLOCK(wdt_lock);
 
 #define TIMER_MARGIN   60
@@ -54,8 +57,8 @@ MODULE_PARM_DESC(mpcore_margin,
        "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default="
                                __MODULE_STRING(TIMER_MARGIN) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -148,7 +151,7 @@ static int mpcore_wdt_set_heartbeat(int t)
  */
 static int mpcore_wdt_open(struct inode *inode, struct file *file)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_pdev);
 
        if (test_and_set_bit(0, &wdt->timer_alive))
                return -EBUSY;
@@ -298,9 +301,9 @@ static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd,
  *     System shutdown handler.  Turn off the watchdog if we're
  *     restarting or halting the system.
  */
-static void mpcore_wdt_shutdown(struct platform_device *dev)
+static void mpcore_wdt_shutdown(struct platform_device *pdev)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
 
        if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
                mpcore_wdt_stop(wdt);
@@ -324,99 +327,79 @@ static struct miscdevice mpcore_wdt_miscdev = {
        .fops           = &mpcore_wdt_fops,
 };
 
-static int __devinit mpcore_wdt_probe(struct platform_device *dev)
+static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
 {
        struct mpcore_wdt *wdt;
        struct resource *res;
        int ret;
 
        /* We only accept one device, and it must have an id of -1 */
-       if (dev->id != -1)
+       if (pdev->id != -1)
                return -ENODEV;
 
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto err_out;
-       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
 
-       wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
-       if (!wdt) {
-               ret = -ENOMEM;
-               goto err_out;
+       wdt = devm_kzalloc(&pdev->dev, sizeof(struct mpcore_wdt), GFP_KERNEL);
+       if (!wdt)
+               return -ENOMEM;
+
+       wdt->dev = &pdev->dev;
+       wdt->irq = platform_get_irq(pdev, 0);
+       if (wdt->irq >= 0) {
+               ret = devm_request_irq(wdt->dev, wdt->irq, mpcore_wdt_fire, 0,
+                               "mpcore_wdt", wdt);
+               if (ret) {
+                       dev_printk(KERN_ERR, wdt->dev,
+                                       "cannot register IRQ%d for watchdog\n",
+                                       wdt->irq);
+                       return ret;
+               }
        }
 
-       wdt->dev = &dev->dev;
-       wdt->irq = platform_get_irq(dev, 0);
-       if (wdt->irq < 0) {
-               ret = -ENXIO;
-               goto err_free;
-       }
-       wdt->base = ioremap(res->start, resource_size(res));
-       if (!wdt->base) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
+       wdt->base = devm_ioremap(wdt->dev, res->start, resource_size(res));
+       if (!wdt->base)
+               return -ENOMEM;
 
-       mpcore_wdt_miscdev.parent = &dev->dev;
+       mpcore_wdt_miscdev.parent = &pdev->dev;
        ret = misc_register(&mpcore_wdt_miscdev);
        if (ret) {
                dev_printk(KERN_ERR, wdt->dev,
                        "cannot register miscdev on minor=%d (err=%d)\n",
                                                        WATCHDOG_MINOR, ret);
-               goto err_misc;
-       }
-
-       ret = request_irq(wdt->irq, mpcore_wdt_fire, 0, "mpcore_wdt", wdt);
-       if (ret) {
-               dev_printk(KERN_ERR, wdt->dev,
-                       "cannot register IRQ%d for watchdog\n", wdt->irq);
-               goto err_irq;
+               return ret;
        }
 
        mpcore_wdt_stop(wdt);
-       platform_set_drvdata(dev, wdt);
-       mpcore_wdt_dev = dev;
+       platform_set_drvdata(pdev, wdt);
+       mpcore_wdt_pdev = pdev;
 
        return 0;
-
-err_irq:
-       misc_deregister(&mpcore_wdt_miscdev);
-err_misc:
-       iounmap(wdt->base);
-err_free:
-       kfree(wdt);
-err_out:
-       return ret;
 }
 
-static int __devexit mpcore_wdt_remove(struct platform_device *dev)
+static int __devexit mpcore_wdt_remove(struct platform_device *pdev)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
-
-       platform_set_drvdata(dev, NULL);
+       platform_set_drvdata(pdev, NULL);
 
        misc_deregister(&mpcore_wdt_miscdev);
 
-       mpcore_wdt_dev = NULL;
+       mpcore_wdt_pdev = NULL;
 
-       free_irq(wdt->irq, wdt);
-       iounmap(wdt->base);
-       kfree(wdt);
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int mpcore_wdt_suspend(struct platform_device *dev, pm_message_t msg)
+static int mpcore_wdt_suspend(struct platform_device *pdev, pm_message_t msg)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
        mpcore_wdt_stop(wdt);           /* Turn the WDT off */
        return 0;
 }
 
-static int mpcore_wdt_resume(struct platform_device *dev)
+static int mpcore_wdt_resume(struct platform_device *pdev)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
        /* re-activate timer */
        if (test_bit(0, &wdt->timer_alive))
                mpcore_wdt_start(wdt);
@@ -442,9 +425,6 @@ static struct platform_driver mpcore_wdt_driver = {
        },
 };
 
-static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. "
-               "mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
-
 static int __init mpcore_wdt_init(void)
 {
        /*
@@ -453,11 +433,12 @@ static int __init mpcore_wdt_init(void)
         */
        if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
                mpcore_wdt_set_heartbeat(TIMER_MARGIN);
-               printk(KERN_INFO "mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n",
+               pr_info("mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n",
                        TIMER_MARGIN);
        }
 
-       printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+       pr_info("MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n",
+               mpcore_noboot, mpcore_margin, nowayout);
 
        return platform_driver_register(&mpcore_wdt_driver);
 }
index 97f8a48d8b7870efbae1b9173d58295f65e2dd71..c53d025e70dfce053b6f05835d737605fa7f4669 100644 (file)
@@ -15,6 +15,8 @@
  * or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -58,8 +60,8 @@ static unsigned int bus_clk;
 static char expect_close;
 static DEFINE_SPINLOCK(mv64x60_wdt_spinlock);
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -100,7 +102,7 @@ static void mv64x60_wdt_handler_enable(void)
        if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE,
                                   MV64x60_WDC_ENABLE_SHIFT)) {
                mv64x60_wdt_service();
-               printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+               pr_notice("watchdog activated\n");
        }
 }
 
@@ -108,7 +110,7 @@ static void mv64x60_wdt_handler_disable(void)
 {
        if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
                                   MV64x60_WDC_ENABLE_SHIFT))
-               printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+               pr_notice("watchdog deactivated\n");
 }
 
 static void mv64x60_wdt_set_timeout(unsigned int timeout)
@@ -139,8 +141,7 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                mv64x60_wdt_handler_disable();
        else {
-               printk(KERN_CRIT
-                      "mv64x60_wdt: unexpected close, not stopping timer!\n");
+               pr_crit("unexpected close, not stopping timer!\n");
                mv64x60_wdt_service();
        }
        expect_close = 0;
@@ -308,7 +309,7 @@ static struct platform_driver mv64x60_wdt_driver = {
 
 static int __init mv64x60_wdt_init(void)
 {
-       printk(KERN_INFO "MV64x60 watchdog driver\n");
+       pr_info("MV64x60 watchdog driver\n");
 
        return platform_driver_register(&mv64x60_wdt_driver);
 }
index 529085b8b8fb0358275b3cbbf65801b5eee74445..ea4c7448b7547255d2c922232d6f529a1be6fc76 100644 (file)
@@ -55,8 +55,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
        "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 809f41c30c4433dfb3e45b53835935608f95753e..6bbb9efc61250ab28eeabcc8441e50a281b9ef16 100644 (file)
@@ -21,6 +21,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -41,7 +43,6 @@
 #define TCO_VERSION "0.01"
 #define TCO_MODULE_NAME "NV_TCO"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
-#define PFX TCO_MODULE_NAME ": "
 
 /* internal variables */
 static unsigned int tcobase;
@@ -60,8 +61,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, "
                            "default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -169,8 +170,7 @@ static int nv_tco_release(struct inode *inode, struct file *file)
        if (tco_expect_close == 42) {
                tco_timer_stop();
        } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping "
-                      "watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                tco_timer_keepalive();
        }
        clear_bit(0, &timer_alive);
@@ -323,15 +323,14 @@ static unsigned char __devinit nv_tco_getdevice(void)
        val &= 0xffff;
        if (val == 0x0001 || val == 0x0000) {
                /* Something is wrong here, bar isn't setup */
-               printk(KERN_ERR PFX "failed to get tcobase address\n");
+               pr_err("failed to get tcobase address\n");
                return 0;
        }
        val &= 0xff00;
        tcobase = val + 0x40;
 
        if (!request_region(tcobase, 0x10, "NV TCO")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                      tcobase);
+               pr_err("I/O address 0x%04x already in use\n", tcobase);
                return 0;
        }
 
@@ -347,7 +346,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
 
        /* Disable SMI caused by TCO */
        if (!request_region(MCP51_SMI_EN(tcobase), 4, "NV TCO")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+               pr_err("I/O address 0x%04x already in use\n",
                       MCP51_SMI_EN(tcobase));
                goto out;
        }
@@ -357,7 +356,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
        val = inl(MCP51_SMI_EN(tcobase));
        release_region(MCP51_SMI_EN(tcobase), 4);
        if (val & MCP51_SMI_EN_TCO) {
-               printk(KERN_ERR PFX "Could not disable SMI caused by TCO\n");
+               pr_err("Could not disable SMI caused by TCO\n");
                goto out;
        }
 
@@ -367,8 +366,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
        pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
        pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
        if (!(val & MCP51_SMBUS_SETUP_B_TCO_REBOOT)) {
-               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot "
-                      "disabled by hardware\n");
+               pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
                goto out;
        }
 
@@ -387,8 +385,8 @@ static int __devinit nv_tco_init(struct platform_device *dev)
                return -ENODEV;
 
        /* Check to see if last reboot was due to watchdog timeout */
-       printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
-              inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not ");
+       pr_info("Watchdog reboot %sdetected\n",
+               inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not ");
 
        /* Clear out the old status */
        outl(TCO_STS_RESET, TCO_STS(tcobase));
@@ -400,14 +398,14 @@ static int __devinit nv_tco_init(struct platform_device *dev)
        if (tco_timer_set_heartbeat(heartbeat)) {
                heartbeat = WATCHDOG_HEARTBEAT;
                tco_timer_set_heartbeat(heartbeat);
-               printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39, "
-                      "using %d\n", heartbeat);
+               pr_info("heartbeat value must be 2<heartbeat<39, using %d\n",
+                       heartbeat);
        }
 
        ret = misc_register(&nv_tco_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
-                      "(err=%d)\n", WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_region;
        }
 
@@ -415,8 +413,8 @@ static int __devinit nv_tco_init(struct platform_device *dev)
 
        tco_timer_stop();
 
-       printk(KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec "
-              "(nowayout=%d)\n", tcobase, heartbeat, nowayout);
+       pr_info("initialized (0x%04x). heartbeat=%d sec (nowayout=%d)\n",
+               tcobase, heartbeat, nowayout);
 
        return 0;
 
@@ -439,8 +437,7 @@ static void __devexit nv_tco_cleanup(void)
        pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
        pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
        if (val & MCP51_SMBUS_SETUP_B_TCO_REBOOT) {
-               printk(KERN_CRIT PFX "Couldn't unset REBOOT bit.  Machine may "
-                      "soon reset\n");
+               pr_crit("Couldn't unset REBOOT bit.  Machine may soon reset\n");
        }
 
        /* Deregister */
@@ -483,8 +480,7 @@ static int __init nv_tco_init_module(void)
 {
        int err;
 
-       printk(KERN_INFO PFX "NV TCO WatchDog Timer Driver v%s\n",
-              TCO_VERSION);
+       pr_info("NV TCO WatchDog Timer Driver v%s\n", TCO_VERSION);
 
        err = platform_driver_register(&nv_tco_driver);
        if (err)
@@ -508,7 +504,7 @@ static void __exit nv_tco_cleanup_module(void)
 {
        platform_device_unregister(nv_tco_platform_device);
        platform_driver_unregister(&nv_tco_driver);
-       printk(KERN_INFO PFX "NV TCO Watchdog Module Unloaded.\n");
+       pr_info("NV TCO Watchdog Module Unloaded\n");
 }
 
 module_init(nv_tco_init_module);
index 7c0d8630e64102f52992ec52b5e35f95da82deda..461208831428e4da609606282af2b56f4c3c81f4 100644 (file)
@@ -52,6 +52,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/watchdog.h>
@@ -95,8 +97,8 @@ MODULE_PARM_DESC(heartbeat,
        "Watchdog heartbeat in seconds. (0 < heartbeat, default="
                                __MODULE_STRING(WD_TIMO) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, S_IRUGO);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, S_IRUGO);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -201,7 +203,7 @@ static void __init octeon_wdt_build_stage1(void)
        uasm_resolve_relocs(relocs, labels);
 
        len = (int)(p - nmi_stage1_insns);
-       pr_debug("Synthesized NMI stage 1 handler (%d instructions).\n", len);
+       pr_debug("Synthesized NMI stage 1 handler (%d instructions)\n", len);
 
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
@@ -627,7 +629,7 @@ static int octeon_wdt_release(struct inode *inode, struct file *file)
                do_coundown = 0;
                octeon_wdt_ping();
        } else {
-               pr_crit("octeon_wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
        }
        clear_bit(0, &octeon_wdt_is_open);
        expect_close = 0;
@@ -684,12 +686,12 @@ static int __init octeon_wdt_init(void)
 
        octeon_wdt_calc_parameters(heartbeat);
 
-       pr_info("octeon_wdt: Initial granularity %d Sec.\n", timeout_sec);
+       pr_info("Initial granularity %d Sec\n", timeout_sec);
 
        ret = misc_register(&octeon_wdt_miscdev);
        if (ret) {
-               pr_err("octeon_wdt: cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto out;
        }
 
index f359ab85c3bc465284c6d3137d60b5e0ef5abad8..55d2f66dbeae85eee71221cdda412f4484868dc6 100644 (file)
@@ -19,6 +19,8 @@
 *                know the wdt reset interval
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -99,7 +101,7 @@ static void xwdt_stop(void)
        iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET);
 
        spin_unlock(&spinlock);
-       printk(KERN_INFO PFX "Stopped!\n");
+       pr_info("Stopped!\n");
 }
 
 static void xwdt_keepalive(void)
@@ -165,7 +167,7 @@ static int xwdt_open(struct inode *inode, struct file *file)
                __module_get(THIS_MODULE);
 
        xwdt_start();
-       printk(KERN_INFO PFX "Started...\n");
+       pr_info("Started...\n");
 
        return nonseekable_open(inode, file);
 }
@@ -175,8 +177,7 @@ static int xwdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                xwdt_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                xwdt_keepalive();
        }
 
@@ -300,22 +301,20 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
                                        "clock-frequency", NULL);
 
        if (pfreq == NULL) {
-               printk(KERN_WARNING PFX
-                       "The watchdog clock frequency cannot be obtained!\n");
+               pr_warn("The watchdog clock frequency cannot be obtained!\n");
                no_timeout = 1;
        }
 
        rc = of_address_to_resource(pdev->dev.of_node, 0, &xdev.res);
        if (rc) {
-               printk(KERN_WARNING PFX "invalid address!\n");
+               pr_warn("invalid address!\n");
                return rc;
        }
 
        tmptr = (u32 *)of_get_property(pdev->dev.of_node,
                                        "xlnx,wdt-interval", NULL);
        if (tmptr == NULL) {
-               printk(KERN_WARNING PFX "Parameter \"xlnx,wdt-interval\""
-                                       " not found in device tree!\n");
+               pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n");
                no_timeout = 1;
        } else {
                xdev.wdt_interval = *tmptr;
@@ -324,8 +323,7 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
        tmptr = (u32 *)of_get_property(pdev->dev.of_node,
                                        "xlnx,wdt-enable-once", NULL);
        if (tmptr == NULL) {
-               printk(KERN_WARNING PFX "Parameter \"xlnx,wdt-enable-once\""
-                                       " not found in device tree!\n");
+               pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n");
                xdev.nowayout = WATCHDOG_NOWAYOUT;
        }
 
@@ -339,20 +337,20 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
        if (!request_mem_region(xdev.res.start,
                        xdev.res.end - xdev.res.start + 1, WATCHDOG_NAME)) {
                rc = -ENXIO;
-               printk(KERN_ERR PFX "memory request failure!\n");
+               pr_err("memory request failure!\n");
                goto err_out;
        }
 
        xdev.base = ioremap(xdev.res.start, xdev.res.end - xdev.res.start + 1);
        if (xdev.base == NULL) {
                rc = -ENOMEM;
-               printk(KERN_ERR PFX "ioremap failure!\n");
+               pr_err("ioremap failure!\n");
                goto release_mem;
        }
 
        rc = xwdt_selftest();
        if (rc == XWT_TIMER_FAILED) {
-               printk(KERN_ERR PFX "SelfTest routine error!\n");
+               pr_err("SelfTest routine error!\n");
                goto unmap_io;
        }
 
@@ -360,20 +358,17 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
 
        rc = misc_register(&xwdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               xwdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      xwdt_miscdev.minor, rc);
                goto unmap_io;
        }
 
        if (no_timeout)
-               printk(KERN_INFO PFX
-                       "driver loaded (timeout=? sec, nowayout=%d)\n",
-                                                   xdev.nowayout);
+               pr_info("driver loaded (timeout=? sec, nowayout=%d)\n",
+                       xdev.nowayout);
        else
-               printk(KERN_INFO PFX
-                       "driver loaded (timeout=%d sec, nowayout=%d)\n",
-                                       timeout, xdev.nowayout);
+               pr_info("driver loaded (timeout=%d sec, nowayout=%d)\n",
+                       timeout, xdev.nowayout);
 
        expect_close = 0;
        clear_bit(0, &driver_open);
index d19ff5145e8260fff0eb102bbbfcd7b058b85eeb..8285d65cd2074ff71b954a16e30e39c719808623 100644 (file)
@@ -26,6 +26,8 @@
  *     Use the driver model and standard identifiers; handle bigger timeouts.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -183,7 +185,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
 
        pm_runtime_put_sync(wdev->dev);
 #else
-       printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+       pr_crit("Unexpected close, not stopping!\n");
 #endif
        wdev->omap_wdt_users = 0;
 
index 1368e4ca3100db5dc9aa9b42cd85cc7a2d79b455..788aa158e78c054eef91dabae21de96fa3e20d32 100644 (file)
@@ -10,6 +10,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -36,7 +38,7 @@
 #define WDT_IN_USE             0
 #define WDT_OK_TO_CLOSE                1
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;             /* module parameter (seconds) */
 static unsigned int wdt_max_duration;  /* (seconds) */
 static unsigned int wdt_tclk;
@@ -210,8 +212,7 @@ static int orion_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                orion_wdt_disable();
        else
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
        clear_bit(WDT_IN_USE, &wdt_status);
        clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
 
@@ -243,7 +244,7 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev)
        if (pdata) {
                wdt_tclk = pdata->tclk;
        } else {
-               printk(KERN_ERR "Orion Watchdog misses platform data\n");
+               pr_err("misses platform data\n");
                return -ENODEV;
        }
 
@@ -263,8 +264,8 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       printk(KERN_INFO "Orion Watchdog Timer: Initial timeout %d sec%s\n",
-                               heartbeat, nowayout ? ", nowayout" : "");
+       pr_info("Initial timeout %d sec%s\n",
+               heartbeat, nowayout ? ", nowayout" : "");
        return 0;
 }
 
@@ -308,7 +309,7 @@ MODULE_DESCRIPTION("Orion Processor Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index e78d8998676885fdf088186063e65883623fcc3f..5afb89b48650a4326298933cf01ec69f3fe84fb7 100644 (file)
@@ -18,6 +18,8 @@
  *      Release 1.1
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
@@ -33,7 +35,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 /* #define DEBUG 1 */
 
@@ -42,7 +43,6 @@
 
 #define VERSION             "1.1"
 #define MODNAME             "pc87413 WDT"
-#define PFX                 MODNAME ": "
 #define DPFX                MODNAME " - DEBUG: "
 
 #define WDT_INDEX_IO_PORT   (io+0)     /* I/O port base (index register) */
@@ -65,7 +65,7 @@ static char expect_close;             /* is the close expected? */
 
 static DEFINE_SPINLOCK(io_lock);       /* to guard us from io races */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* -- Low level function ----------------------------------------*/
 
@@ -87,7 +87,7 @@ static inline void pc87413_select_wdt_out(void)
        outb_p(cr_data, WDT_DATA_IO_PORT);
 
 #ifdef DEBUG
-       printk(KERN_INFO DPFX
+       pr_info(DPFX
                "Select multiple pin,pin55,as WDT output: Bit7 to 1: %d\n",
                                                                cr_data);
 #endif
@@ -111,7 +111,7 @@ static inline void pc87413_enable_swc(void)
        outb_p(cr_data, WDT_DATA_IO_PORT);      /* Index0x30_bit0P1 */
 
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n");
+       pr_info(DPFX "pc87413 - Enable SWC functions\n");
 #endif
 }
 
@@ -132,7 +132,7 @@ static void pc87413_get_swc_base_addr(void)
 
        swc_base_addr = (addr_h << 8) + addr_l;
 #ifdef DEBUG
-       printk(KERN_INFO DPFX
+       pr_info(DPFX
                "Read SWC I/O Base Address: low %d, high %d, res %d\n",
                                                addr_l, addr_h, swc_base_addr);
 #endif
@@ -145,7 +145,7 @@ static inline void pc87413_swc_bank3(void)
        /* Step 4: Select Bank3 of SWC */
        outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Select Bank3 of SWC\n");
+       pr_info(DPFX "Select Bank3 of SWC\n");
 #endif
 }
 
@@ -156,7 +156,7 @@ static inline void pc87413_programm_wdto(char pc87413_time)
        /* Step 5: Programm WDTO, Twd. */
        outb_p(pc87413_time, swc_base_addr + WDTO);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time);
+       pr_info(DPFX "Set WDTO to %d minutes\n", pc87413_time);
 #endif
 }
 
@@ -167,7 +167,7 @@ static inline void pc87413_enable_wden(void)
        /* Step 6: Enable WDEN */
        outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Enable WDEN\n");
+       pr_info(DPFX "Enable WDEN\n");
 #endif
 }
 
@@ -177,7 +177,7 @@ static inline void pc87413_enable_sw_wd_tren(void)
        /* Enable SW_WD_TREN */
        outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Enable SW_WD_TREN\n");
+       pr_info(DPFX "Enable SW_WD_TREN\n");
 #endif
 }
 
@@ -188,7 +188,7 @@ static inline void pc87413_disable_sw_wd_tren(void)
        /* Disable SW_WD_TREN */
        outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n");
+       pr_info(DPFX "pc87413 - Disable SW_WD_TREN\n");
 #endif
 }
 
@@ -199,7 +199,7 @@ static inline void pc87413_enable_sw_wd_trg(void)
        /* Enable SW_WD_TRG */
        outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n");
+       pr_info(DPFX "pc87413 - Enable SW_WD_TRG\n");
 #endif
 }
 
@@ -210,7 +210,7 @@ static inline void pc87413_disable_sw_wd_trg(void)
        /* Disable SW_WD_TRG */
        outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Disable SW_WD_TRG\n");
+       pr_info(DPFX "Disable SW_WD_TRG\n");
 #endif
 }
 
@@ -284,8 +284,7 @@ static int pc87413_open(struct inode *inode, struct file *file)
        /* Reload and activate timer */
        pc87413_refresh();
 
-       printk(KERN_INFO MODNAME
-               "Watchdog enabled. Timeout set to %d minute(s).\n", timeout);
+       pr_info("Watchdog enabled. Timeout set to %d minute(s).\n", timeout);
 
        return nonseekable_open(inode, file);
 }
@@ -308,11 +307,9 @@ static int pc87413_release(struct inode *inode, struct file *file)
 
        if (expect_close == 42) {
                pc87413_disable();
-               printk(KERN_INFO MODNAME
-                               "Watchdog disabled, sleeping again...\n");
+               pr_info("Watchdog disabled, sleeping again...\n");
        } else {
-               printk(KERN_CRIT MODNAME
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                pc87413_refresh();
        }
        clear_bit(0, &timer_enabled);
@@ -428,7 +425,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd,
        case WDIOC_KEEPALIVE:
                pc87413_refresh();
 #ifdef DEBUG
-               printk(KERN_INFO DPFX "keepalive\n");
+               pr_info(DPFX "keepalive\n");
 #endif
                return 0;
        case WDIOC_SETTIMEOUT:
@@ -508,7 +505,7 @@ static int __init pc87413_init(void)
 {
        int ret;
 
-       printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n",
+       pr_info("Version " VERSION " at io 0x%X\n",
                                                        WDT_INDEX_IO_PORT);
 
        if (!request_muxed_region(io, 2, MODNAME))
@@ -516,26 +513,23 @@ static int __init pc87413_init(void)
 
        ret = register_reboot_notifier(&pc87413_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
        }
 
        ret = misc_register(&pc87413_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto reboot_unreg;
        }
-       printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
+       pr_info("initialized. timeout=%d min\n", timeout);
 
        pc87413_select_wdt_out();
        pc87413_enable_swc();
        pc87413_get_swc_base_addr();
 
        if (!request_region(swc_base_addr, 0x20, MODNAME)) {
-               printk(KERN_ERR PFX
-                       "cannot request SWC region at 0x%x\n", swc_base_addr);
+               pr_err("cannot request SWC region at 0x%x\n", swc_base_addr);
                ret = -EBUSY;
                goto misc_unreg;
        }
@@ -568,14 +562,14 @@ static void __exit pc87413_exit(void)
        /* Stop the timer before we leave */
        if (!nowayout) {
                pc87413_disable();
-               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+               pr_info("Watchdog disabled\n");
        }
 
        misc_deregister(&pc87413_miscdev);
        unregister_reboot_notifier(&pc87413_notifier);
        release_region(swc_base_addr, 0x20);
 
-       printk(KERN_INFO MODNAME " watchdog component driver removed.\n");
+       pr_info("watchdog component driver removed\n");
 }
 
 module_init(pc87413_init);
@@ -597,7 +591,7 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in minutes (default="
                                __MODULE_STRING(DEFAULT_TIMEOUT) ").");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 06f7922606c0cac89722d6ba53a2dc1ecc39a125..75694cf24f86713830dd3075cadea5666cdc84be 100644 (file)
@@ -51,6 +51,8 @@
  *     http://www.pcwatchdog.com/
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>      /* For module specific items */
 #include <linux/moduleparam.h> /* For new moduleparam's */
 #include <linux/types.h>       /* For standard types (like size_t) */
@@ -75,7 +77,6 @@
 #define WATCHDOG_DATE "18 Feb 2007"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
-#define PFX WATCHDOG_NAME ": "
 #define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n"
 
 /*
@@ -203,8 +204,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
        "(2 <= heartbeat <= 7200 or 0=delay-time from dip-switches, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -220,8 +221,7 @@ static int send_isa_command(int cmd)
        int port0, last_port0;  /* Double read for stabilising */
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
-                       cmd);
+               pr_debug("sending following data cmd=0x%02x\n", cmd);
 
        /* The WCMD bit must be 1 and the command is only 4 bits in size */
        control_status = (cmd & 0x0F) | WD_WCMD;
@@ -240,9 +240,8 @@ static int send_isa_command(int cmd)
        }
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "received following data for "
-                       "cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
-                       cmd, port0, last_port0);
+               pr_debug("received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+                        cmd, port0, last_port0);
 
        return port0;
 }
@@ -271,8 +270,7 @@ static int set_command_mode(void)
        pcwd_private.command_mode = found;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "command_mode=%d\n",
-                               pcwd_private.command_mode);
+               pr_debug("command_mode=%d\n", pcwd_private.command_mode);
 
        return found;
 }
@@ -288,8 +286,7 @@ static void unset_command_mode(void)
        pcwd_private.command_mode = 0;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "command_mode=%d\n",
-                               pcwd_private.command_mode);
+               pr_debug("command_mode=%d\n", pcwd_private.command_mode);
 }
 
 static inline void pcwd_check_temperature_support(void)
@@ -336,17 +333,14 @@ static void pcwd_show_card_info(void)
 
        /* Get some extra info from the hardware (in command/debug/diag mode) */
        if (pcwd_private.revision == PCWD_REVISION_A)
-               printk(KERN_INFO PFX
-                       "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n",
-                                                       pcwd_private.io_addr);
+               pr_info("ISA-PC Watchdog (REV.A) detected at port 0x%04x\n",
+                       pcwd_private.io_addr);
        else if (pcwd_private.revision == PCWD_REVISION_C) {
                pcwd_get_firmware();
-               printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port "
-                       "0x%04x (Firmware version: %s)\n",
+               pr_info("ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
                        pcwd_private.io_addr, pcwd_private.fw_ver_str);
                option_switches = pcwd_get_option_switches();
-               printk(KERN_INFO PFX "Option switches (0x%02x): "
-                       "Temperature Reset Enable=%s, Power On Delay=%s\n",
+               pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
                        option_switches,
                        ((option_switches & 0x10) ? "ON" : "OFF"),
                        ((option_switches & 0x08) ? "ON" : "OFF"));
@@ -359,22 +353,18 @@ static void pcwd_show_card_info(void)
        }
 
        if (pcwd_private.supports_temp)
-               printk(KERN_INFO PFX "Temperature Option Detected\n");
+               pr_info("Temperature Option Detected\n");
 
        if (pcwd_private.boot_status & WDIOF_CARDRESET)
-               printk(KERN_INFO PFX
-                       "Previous reboot was caused by the card\n");
+               pr_info("Previous reboot was caused by the card\n");
 
        if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
-               printk(KERN_EMERG PFX
-                       "Card senses a CPU Overheat. Panicking!\n");
-               printk(KERN_EMERG PFX
-                       "CPU Overheat\n");
+               pr_emerg("Card senses a CPU Overheat. Panicking!\n");
+               pr_emerg("CPU Overheat\n");
        }
 
        if (pcwd_private.boot_status == 0)
-               printk(KERN_INFO PFX
-                       "No previous trip detected - Cold boot or reset\n");
+               pr_info("No previous trip detected - Cold boot or reset\n");
 }
 
 static void pcwd_timer_ping(unsigned long data)
@@ -404,8 +394,7 @@ static void pcwd_timer_ping(unsigned long data)
 
                spin_unlock(&pcwd_private.io_lock);
        } else {
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
        }
 }
 
@@ -426,13 +415,13 @@ static int pcwd_start(void)
                stat_reg = inb_p(pcwd_private.io_addr + 2);
                spin_unlock(&pcwd_private.io_lock);
                if (stat_reg & WD_WDIS) {
-                       printk(KERN_INFO PFX "Could not start watchdog\n");
+                       pr_info("Could not start watchdog\n");
                        return -EIO;
                }
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog started\n");
+               pr_debug("Watchdog started\n");
 
        return 0;
 }
@@ -454,13 +443,13 @@ static int pcwd_stop(void)
                stat_reg = inb_p(pcwd_private.io_addr + 2);
                spin_unlock(&pcwd_private.io_lock);
                if ((stat_reg & WD_WDIS) == 0) {
-                       printk(KERN_INFO PFX "Could not stop watchdog\n");
+                       pr_info("Could not stop watchdog\n");
                        return -EIO;
                }
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog stopped\n");
+               pr_debug("Watchdog stopped\n");
 
        return 0;
 }
@@ -471,7 +460,7 @@ static int pcwd_keepalive(void)
        pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+               pr_debug("Watchdog keepalive signal send\n");
 
        return 0;
 }
@@ -484,8 +473,7 @@ static int pcwd_set_heartbeat(int t)
        heartbeat = t;
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
-                      heartbeat);
+               pr_debug("New heartbeat: %d\n", heartbeat);
 
        return 0;
 }
@@ -518,8 +506,7 @@ static int pcwd_get_status(int *status)
                if (control_status & WD_T110) {
                        *status |= WDIOF_OVERHEAT;
                        if (temp_panic) {
-                               printk(KERN_INFO PFX
-                                       "Temperature overheat trip!\n");
+                               pr_info("Temperature overheat trip!\n");
                                kernel_power_off();
                        }
                }
@@ -530,8 +517,7 @@ static int pcwd_get_status(int *status)
                if (control_status & WD_REVC_TTRP) {
                        *status |= WDIOF_OVERHEAT;
                        if (temp_panic) {
-                               printk(KERN_INFO PFX
-                                       "Temperature overheat trip!\n");
+                               pr_info("Temperature overheat trip!\n");
                                kernel_power_off();
                        }
                }
@@ -548,16 +534,14 @@ static int pcwd_clear_status(void)
                spin_lock(&pcwd_private.io_lock);
 
                if (debug >= VERBOSE)
-                       printk(KERN_INFO PFX
-                                       "clearing watchdog trip status\n");
+                       pr_info("clearing watchdog trip status\n");
 
                control_status = inb_p(pcwd_private.io_addr + 1);
 
                if (debug >= DEBUG) {
-                       printk(KERN_DEBUG PFX "status was: 0x%02x\n",
-                               control_status);
-                       printk(KERN_DEBUG PFX "sending: 0x%02x\n",
-                               (control_status & WD_REVC_R2DS));
+                       pr_debug("status was: 0x%02x\n", control_status);
+                       pr_debug("sending: 0x%02x\n",
+                                (control_status & WD_REVC_R2DS));
                }
 
                /* clear reset status & Keep Relay 2 disable state as it is */
@@ -588,8 +572,7 @@ static int pcwd_get_temperature(int *temperature)
        spin_unlock(&pcwd_private.io_lock);
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "temperature is: %d F\n",
-                       *temperature);
+               pr_debug("temperature is: %d F\n", *temperature);
        }
 
        return 0;
@@ -720,8 +703,7 @@ static int pcwd_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                pcwd_stop();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                pcwd_keepalive();
        }
        expect_close = 0;
@@ -828,11 +810,10 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
        int retval;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_match id=%d\n", id);
 
        if (!request_region(base_addr, 4, "PCWD")) {
-               printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
+               pr_info("Port 0x%04x unavailable\n", base_addr);
                return 0;
        }
 
@@ -870,21 +851,20 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
        int ret;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_probe id=%d\n", id);
 
        cards_found++;
        if (cards_found == 1)
-               printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n",
+               pr_info("v%s Ken Hollis (kenji@bitgate.com)\n",
                                                        WATCHDOG_VERSION);
 
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
        if (pcwd_ioports[id] == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               pr_err("No I/O-Address for card detected\n");
                return -ENODEV;
        }
        pcwd_private.io_addr = pcwd_ioports[id];
@@ -896,8 +876,8 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
 
        if (!request_region(pcwd_private.io_addr,
                (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       pcwd_private.io_addr);
+               pr_err("I/O address 0x%04x already in use\n",
+                      pcwd_private.io_addr);
                ret = -EIO;
                goto error_request_region;
        }
@@ -932,30 +912,27 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
           if not reset to the default */
        if (pcwd_set_heartbeat(heartbeat)) {
                pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                 "heartbeat value must be 2 <= heartbeat <= 7200, using %d\n",
-                                                       WATCHDOG_HEARTBEAT);
+               pr_info("heartbeat value must be 2 <= heartbeat <= 7200, using %d\n",
+                       WATCHDOG_HEARTBEAT);
        }
 
        if (pcwd_private.supports_temp) {
                ret = misc_register(&temp_miscdev);
                if (ret) {
-                       printk(KERN_ERR PFX
-                           "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto error_misc_register_temp;
                }
        }
 
        ret = misc_register(&pcwd_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto error_misc_register_watchdog;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
@@ -975,8 +952,7 @@ error_request_region:
 static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
 {
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_remove id=%d\n", id);
 
        if (!pcwd_private.io_addr)
                return 1;
@@ -1000,8 +976,7 @@ static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
 static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
 {
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_shutdown id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_shutdown id=%d\n", id);
 
        pcwd_stop();
 }
@@ -1025,7 +1000,7 @@ static int __init pcwd_init_module(void)
 static void __exit pcwd_cleanup_module(void)
 {
        isa_unregister_driver(&pcwd_isa_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(pcwd_init_module);
index b8d14f88f0b53bec64e81164538d605d7653ef48..c891399bed6ae9022915cbe3c12e566aada25f38 100644 (file)
@@ -32,6 +32,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>      /* For module specific items */
 #include <linux/moduleparam.h> /* For new moduleparam's */
 #include <linux/types.h>       /* For standard types (like size_t) */
@@ -54,8 +56,7 @@
 #define WATCHDOG_VERSION "1.03"
 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
 #define WATCHDOG_NAME "pcwd_pci"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n"
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION
 
 /* Stuff for the PCI ID's  */
 #ifndef PCI_VENDOR_ID_QUICKLOGIC
@@ -145,8 +146,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
        "(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -159,8 +160,8 @@ static int send_command(int cmd, int *msb, int *lsb)
        int got_response, count;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "sending following data "
-               "cmd=0x%02x msb=0x%02x lsb=0x%02x\n", cmd, *msb, *lsb);
+               pr_debug("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n",
+                        cmd, *msb, *lsb);
 
        spin_lock(&pcipcwd_private.io_lock);
        /* If a command requires data it should be written first.
@@ -185,12 +186,10 @@ static int send_command(int cmd, int *msb, int *lsb)
 
        if (debug >= DEBUG) {
                if (got_response) {
-                       printk(KERN_DEBUG PFX
-                               "time to process command was: %d ms\n",
-                               count);
+                       pr_debug("time to process command was: %d ms\n",
+                                count);
                } else {
-                       printk(KERN_DEBUG PFX
-                               "card did not respond on command!\n");
+                       pr_debug("card did not respond on command!\n");
                }
        }
 
@@ -203,9 +202,8 @@ static int send_command(int cmd, int *msb, int *lsb)
                inb_p(pcipcwd_private.io_addr + 6);
 
                if (debug >= DEBUG)
-                       printk(KERN_DEBUG PFX "received following data for "
-                               "cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
-                               cmd, *msb, *lsb);
+                       pr_debug("received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
+                                cmd, *msb, *lsb);
        }
 
        spin_unlock(&pcipcwd_private.io_lock);
@@ -243,27 +241,23 @@ static void pcipcwd_show_card_info(void)
        /* Get switch settings */
        option_switches = pcipcwd_get_option_switches();
 
-       printk(KERN_INFO PFX "Found card at port "
-               "0x%04x (Firmware: %s) %s temp option\n",
+       pr_info("Found card at port 0x%04x (Firmware: %s) %s temp option\n",
                (int) pcipcwd_private.io_addr, fw_ver_str,
                (pcipcwd_private.supports_temp ? "with" : "without"));
 
-       printk(KERN_INFO PFX "Option switches (0x%02x): "
-               "Temperature Reset Enable=%s, Power On Delay=%s\n",
+       pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
                option_switches,
                ((option_switches & 0x10) ? "ON" : "OFF"),
                ((option_switches & 0x08) ? "ON" : "OFF"));
 
        if (pcipcwd_private.boot_status & WDIOF_CARDRESET)
-               printk(KERN_INFO PFX
-                       "Previous reset was caused by the Watchdog card\n");
+               pr_info("Previous reset was caused by the Watchdog card\n");
 
        if (pcipcwd_private.boot_status & WDIOF_OVERHEAT)
-               printk(KERN_INFO PFX "Card sensed a CPU Overheat\n");
+               pr_info("Card sensed a CPU Overheat\n");
 
        if (pcipcwd_private.boot_status == 0)
-               printk(KERN_INFO PFX
-                       "No previous trip detected - Cold boot or reset\n");
+               pr_info("No previous trip detected - Cold boot or reset\n");
 }
 
 static int pcipcwd_start(void)
@@ -278,12 +272,12 @@ static int pcipcwd_start(void)
        spin_unlock(&pcipcwd_private.io_lock);
 
        if (stat_reg & WD_PCI_WDIS) {
-               printk(KERN_ERR PFX "Card timer not enabled\n");
+               pr_err("Card timer not enabled\n");
                return -1;
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog started\n");
+               pr_debug("Watchdog started\n");
 
        return 0;
 }
@@ -303,13 +297,12 @@ static int pcipcwd_stop(void)
        spin_unlock(&pcipcwd_private.io_lock);
 
        if (!(stat_reg & WD_PCI_WDIS)) {
-               printk(KERN_ERR PFX
-                       "Card did not acknowledge disable attempt\n");
+               pr_err("Card did not acknowledge disable attempt\n");
                return -1;
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog stopped\n");
+               pr_debug("Watchdog stopped\n");
 
        return 0;
 }
@@ -322,7 +315,7 @@ static int pcipcwd_keepalive(void)
        spin_unlock(&pcipcwd_private.io_lock);
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+               pr_debug("Watchdog keepalive signal send\n");
 
        return 0;
 }
@@ -340,8 +333,7 @@ static int pcipcwd_set_heartbeat(int t)
 
        heartbeat = t;
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
-                      heartbeat);
+               pr_debug("New heartbeat: %d\n", heartbeat);
 
        return 0;
 }
@@ -357,12 +349,11 @@ static int pcipcwd_get_status(int *status)
        if (control_status & WD_PCI_TTRP) {
                *status |= WDIOF_OVERHEAT;
                if (temp_panic)
-                       panic(PFX "Temperature overheat trip!\n");
+                       panic(KBUILD_MODNAME ": Temperature overheat trip!\n");
        }
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n",
-                      control_status);
+               pr_debug("Control Status #1: 0x%02x\n", control_status);
 
        return 0;
 }
@@ -374,14 +365,14 @@ static int pcipcwd_clear_status(void)
        int reset_counter;
 
        if (debug >= VERBOSE)
-               printk(KERN_INFO PFX "clearing watchdog trip status & LED\n");
+               pr_info("clearing watchdog trip status & LED\n");
 
        control_status = inb_p(pcipcwd_private.io_addr + 1);
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
-               printk(KERN_DEBUG PFX "sending: 0x%02x\n",
-                      (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
+               pr_debug("status was: 0x%02x\n", control_status);
+               pr_debug("sending: 0x%02x\n",
+                        (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
        }
 
        /* clear trip status & LED and keep mode of relay 2 */
@@ -394,8 +385,7 @@ static int pcipcwd_clear_status(void)
        send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter);
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "reset count was: 0x%02x\n",
-                      reset_counter);
+               pr_debug("reset count was: 0x%02x\n", reset_counter);
        }
 
        return 0;
@@ -418,8 +408,7 @@ static int pcipcwd_get_temperature(int *temperature)
        *temperature = (*temperature * 9 / 5) + 32;
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "temperature is: %d F\n",
-                      *temperature);
+               pr_debug("temperature is: %d F\n", *temperature);
        }
 
        return 0;
@@ -437,8 +426,7 @@ static int pcipcwd_get_timeleft(int *time_left)
        *time_left = (msb << 8) + lsb;
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Time left before next reboot: %d\n",
-                      *time_left);
+               pr_debug("Time left before next reboot: %d\n", *time_left);
 
        return 0;
 }
@@ -583,8 +571,7 @@ static int pcipcwd_open(struct inode *inode, struct file *file)
        /* /dev/watchdog can only be opened once */
        if (test_and_set_bit(0, &is_active)) {
                if (debug >= VERBOSE)
-                       printk(KERN_ERR PFX
-                               "Attempt to open already opened device.\n");
+                       pr_err("Attempt to open already opened device\n");
                return -EBUSY;
        }
 
@@ -602,8 +589,7 @@ static int pcipcwd_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                pcipcwd_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                pcipcwd_keepalive();
        }
        expect_release = 0;
@@ -703,20 +689,20 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
 
        cards_found++;
        if (cards_found == 1)
-               printk(KERN_INFO PFX DRIVER_VERSION);
+               pr_info("%s\n", DRIVER_VERSION);
 
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
        if (pci_enable_device(pdev)) {
-               printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
+               pr_err("Not possible to enable PCI Device\n");
                return -ENODEV;
        }
 
        if (pci_resource_start(pdev, 0) == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               pr_err("No I/O-Address for card detected\n");
                ret = -ENODEV;
                goto err_out_disable_device;
        }
@@ -725,8 +711,8 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
        pcipcwd_private.io_addr = pci_resource_start(pdev, 0);
 
        if (pci_request_regions(pdev, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       (int) pcipcwd_private.io_addr);
+               pr_err("I/O address 0x%04x already in use\n",
+                      (int) pcipcwd_private.io_addr);
                ret = -EIO;
                goto err_out_disable_device;
        }
@@ -755,36 +741,33 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
         * if not reset to the default */
        if (pcipcwd_set_heartbeat(heartbeat)) {
                pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                       "heartbeat value must be 0<heartbeat<65536, using %d\n",
+               pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
                        WATCHDOG_HEARTBEAT);
        }
 
        ret = register_reboot_notifier(&pcipcwd_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto err_out_release_region;
        }
 
        if (pcipcwd_private.supports_temp) {
                ret = misc_register(&pcipcwd_temp_miscdev);
                if (ret != 0) {
-                       printk(KERN_ERR PFX "cannot register miscdev on "
-                               "minor=%d (err=%d)\n", TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto err_out_unregister_reboot;
                }
        }
 
        ret = misc_register(&pcipcwd_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto err_out_misc_deregister;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
@@ -842,7 +825,7 @@ static void __exit pcipcwd_cleanup_module(void)
 {
        pci_unregister_driver(&pcipcwd_driver);
 
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(pcipcwd_init_module);
index d8de1ddd176add762617b9dc122f79a5426ed1ab..7b14d184792705d3b60ea6fba20041be351a186d 100644 (file)
@@ -24,6 +24,8 @@
  *     http://www.berkprod.com/ or http://www.pcwatchdog.com/
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>      /* For module specific items */
 #include <linux/moduleparam.h> /* For new moduleparam's */
 #include <linux/types.h>       /* For standard types (like size_t) */
 #include <linux/hid.h>         /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
 #include <linux/uaccess.h>     /* For copy_to_user/put_user/... */
 
-
 #ifdef CONFIG_USB_DEBUG
-       static int debug = 1;
+static int debug = 1;
 #else
-       static int debug;
+static int debug;
 #endif
 
 /* Use our own dbg macro */
+
 #undef dbg
-#define dbg(format, arg...) \
-       do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0)
+#ifndef DEBUG
+#define DEBUG
+#endif
+#define dbg(format, ...)                               \
+do {                                                   \
+       if (debug)                                      \
+               pr_debug(format "\n", ##__VA_ARGS__);   \
+} while (0)
 
 /* Module and Version Information */
 #define DRIVER_VERSION "1.02"
@@ -60,7 +68,6 @@
 #define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
 #define DRIVER_LICENSE "GPL"
 #define DRIVER_NAME "pcwd_usb"
-#define PFX DRIVER_NAME ": "
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -80,8 +87,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
        "(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -220,8 +227,8 @@ static void usb_pcwd_intr_done(struct urb *urb)
 resubmit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
-               printk(KERN_ERR PFX "can't resubmit intr, "
-                       "usb_submit_urb failed with result %d\n", retval);
+               pr_err("can't resubmit intr, usb_submit_urb failed with result %d\n",
+                      retval);
 }
 
 static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd,
@@ -284,8 +291,7 @@ static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
                                                                &msb, &lsb);
 
        if ((retval == 0) || (lsb == 0)) {
-               printk(KERN_ERR PFX
-                               "Card did not acknowledge enable attempt\n");
+               pr_err("Card did not acknowledge enable attempt\n");
                return -1;
        }
 
@@ -303,8 +309,7 @@ static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
                                                                &msb, &lsb);
 
        if ((retval == 0) || (lsb != 0)) {
-               printk(KERN_ERR PFX
-                       "Card did not acknowledge disable attempt\n");
+               pr_err("Card did not acknowledge disable attempt\n");
                return -1;
        }
 
@@ -506,8 +511,7 @@ static int usb_pcwd_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                usb_pcwd_stop(usb_pcwd_device);
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                usb_pcwd_keepalive(usb_pcwd_device);
        }
        expect_release = 0;
@@ -627,7 +631,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        cards_found++;
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
@@ -636,8 +640,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        /* check out that we have a HID device */
        if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
-               printk(KERN_ERR PFX
-                       "The device isn't a Human Interface Device\n");
+               pr_err("The device isn't a Human Interface Device\n");
                return -ENODEV;
        }
 
@@ -646,7 +649,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        if (!usb_endpoint_is_int_in(endpoint)) {
                /* we didn't find a Interrupt endpoint with direction IN */
-               printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n");
+               pr_err("Couldn't find an INTR & IN endpoint\n");
                return -ENODEV;
        }
 
@@ -657,7 +660,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
        /* allocate memory for our device and initialize it */
        usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
        if (usb_pcwd == NULL) {
-               printk(KERN_ERR PFX "Out of memory\n");
+               pr_err("Out of memory\n");
                goto error;
        }
 
@@ -674,14 +677,14 @@ static int usb_pcwd_probe(struct usb_interface *interface,
        usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size,
                                        GFP_ATOMIC, &usb_pcwd->intr_dma);
        if (!usb_pcwd->intr_buffer) {
-               printk(KERN_ERR PFX "Out of memory\n");
+               pr_err("Out of memory\n");
                goto error;
        }
 
        /* allocate the urb's */
        usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!usb_pcwd->intr_urb) {
-               printk(KERN_ERR PFX "Out of memory\n");
+               pr_err("Out of memory\n");
                goto error;
        }
 
@@ -694,7 +697,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        /* register our interrupt URB with the USB system */
        if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
-               printk(KERN_ERR PFX "Problem registering interrupt URB\n");
+               pr_err("Problem registering interrupt URB\n");
                retval = -EIO; /* failure */
                goto error;
        }
@@ -713,15 +716,13 @@ static int usb_pcwd_probe(struct usb_interface *interface,
        else
                sprintf(fw_ver_str, "<card no answer>");
 
-       printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
-               fw_ver_str);
+       pr_info("Found card (Firmware: %s) with temp option\n", fw_ver_str);
 
        /* Get switch settings */
        usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy,
                                                        &option_switches);
 
-       printk(KERN_INFO PFX "Option switches (0x%02x): "
-               "Temperature Reset Enable=%s, Power On Delay=%s\n",
+       pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
                option_switches,
                ((option_switches & 0x10) ? "ON" : "OFF"),
                ((option_switches & 0x08) ? "ON" : "OFF"));
@@ -734,39 +735,34 @@ static int usb_pcwd_probe(struct usb_interface *interface,
         * if not reset to the default */
        if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
                usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                       "heartbeat value must be 0<heartbeat<65536, using %d\n",
+               pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
                        WATCHDOG_HEARTBEAT);
        }
 
        retval = register_reboot_notifier(&usb_pcwd_notifier);
        if (retval != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n",
-                       retval);
+               pr_err("cannot register reboot notifier (err=%d)\n", retval);
                goto error;
        }
 
        retval = misc_register(&usb_pcwd_temperature_miscdev);
        if (retval != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       TEMP_MINOR, retval);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      TEMP_MINOR, retval);
                goto err_out_unregister_reboot;
        }
 
        retval = misc_register(&usb_pcwd_miscdev);
        if (retval != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, retval);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, retval);
                goto err_out_misc_deregister;
        }
 
        /* we can register the device now, as it is ready */
        usb_set_intfdata(interface, usb_pcwd);
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
@@ -824,7 +820,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
 
        mutex_unlock(&disconnect_mutex);
 
-       printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");
+       pr_info("USB PC Watchdog disconnected\n");
 }
 
 module_usb_driver(usb_pcwd_driver);
index 2d22e996e9963cedaf656aa1c82867894d14c906..7d3d471f810c5e918926b3353ef3844187f47833 100644 (file)
@@ -5,6 +5,8 @@
  *   Sean MacLennan <smaclennan@pikatech.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -23,7 +25,6 @@
 #include <linux/of_platform.h>
 
 #define DRV_NAME "PIKA-WDT"
-#define PFX DRV_NAME ": "
 
 /* Hardware timeout in seconds */
 #define WDT_HW_TIMEOUT 2
@@ -38,8 +39,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
        "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -90,7 +91,7 @@ static void pikawdt_ping(unsigned long data)
                pikawdt_reset();
                mod_timer(&pikawdt_private.timer, jiffies + WDT_TIMEOUT);
        } else
-               printk(KERN_CRIT PFX "I will reset your machine !\n");
+               pr_crit("I will reset your machine !\n");
 }
 
 
@@ -228,14 +229,14 @@ static int __init pikawdt_init(void)
 
        np = of_find_compatible_node(NULL, NULL, "pika,fpga");
        if (np == NULL) {
-               printk(KERN_ERR PFX "Unable to find fpga.\n");
+               pr_err("Unable to find fpga\n");
                return -ENOENT;
        }
 
        pikawdt_private.fpga = of_iomap(np, 0);
        of_node_put(np);
        if (pikawdt_private.fpga == NULL) {
-               printk(KERN_ERR PFX "Unable to map fpga.\n");
+               pr_err("Unable to map fpga\n");
                return -ENOMEM;
        }
 
@@ -244,7 +245,7 @@ static int __init pikawdt_init(void)
        /* POST information is in the sd area. */
        np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
        if (np == NULL) {
-               printk(KERN_ERR PFX "Unable to find fpga-sd.\n");
+               pr_err("Unable to find fpga-sd\n");
                ret = -ENOENT;
                goto out;
        }
@@ -252,7 +253,7 @@ static int __init pikawdt_init(void)
        fpga = of_iomap(np, 0);
        of_node_put(np);
        if (fpga == NULL) {
-               printk(KERN_ERR PFX "Unable to map fpga-sd.\n");
+               pr_err("Unable to map fpga-sd\n");
                ret = -ENOMEM;
                goto out;
        }
@@ -271,12 +272,12 @@ static int __init pikawdt_init(void)
 
        ret = misc_register(&pikawdt_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX "Unable to register miscdev.\n");
+               pr_err("Unable to register miscdev\n");
                goto out;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-                                                       heartbeat, nowayout);
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
        return 0;
 
 out:
index dfae030a7ef2553ee6e2d44b59834bc4e3e57003..6b8432f61d05d922b0279530426429fa9d687cd8 100644 (file)
@@ -8,33 +8,32 @@
  * Based on sa1100 driver,
  * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
  *
- * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
+ * 2005-2006 (c) MontaVista Software, Inc.
+ *
+ * (C) 2012 Wolfram Sang, Pengutronix
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 #include <mach/hardware.h>
 
-#define MODULE_NAME "PNX4008-WDT: "
-
 /* WatchDog Timer - Chapter 23 Page 207 */
 
 #define DEFAULT_HEARTBEAT 19
 
 #define WDOG_COUNTER_RATE 13000000     /*the counter clock is 13 MHz fixed */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-static int heartbeat = DEFAULT_HEARTBEAT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
 
 static DEFINE_SPINLOCK(io_lock);
-static unsigned long wdt_status;
-#define WDT_IN_USE        0
-#define WDT_OK_TO_CLOSE   1
-#define WDT_REGION_INITED 2
-#define WDT_DEVICE_INITED 3
-
-static unsigned long boot_status;
-
-static struct resource *wdt_mem;
 static void __iomem    *wdt_base;
 struct clk             *wdt_clk;
 
-static void wdt_enable(void)
+static int pnx4008_wdt_start(struct watchdog_device *wdd)
 {
        spin_lock(&io_lock);
 
        /* stop counter, initiate counter reset */
-       __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
+       writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
        /*wait for reset to complete. 100% guarantee event */
-       while (__raw_readl(WDTIM_COUNTER(wdt_base)))
+       while (readl(WDTIM_COUNTER(wdt_base)))
                cpu_relax();
        /* internal and external reset, stop after that */
-       __raw_writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0,
-               WDTIM_MCTRL(wdt_base));
+       writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0, WDTIM_MCTRL(wdt_base));
        /* configure match output */
-       __raw_writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
+       writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
        /* clear interrupt, just in case */
-       __raw_writel(MATCH_INT, WDTIM_INT(wdt_base));
+       writel(MATCH_INT, WDTIM_INT(wdt_base));
        /* the longest pulse period 65541/(13*10^6) seconds ~ 5 ms. */
-       __raw_writel(0xFFFF, WDTIM_PULSE(wdt_base));
-       __raw_writel(heartbeat * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
+       writel(0xFFFF, WDTIM_PULSE(wdt_base));
+       writel(wdd->timeout * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
        /*enable counter, stop when debugger active */
-       __raw_writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
+       writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
 
        spin_unlock(&io_lock);
+       return 0;
 }
 
-static void wdt_disable(void)
+static int pnx4008_wdt_stop(struct watchdog_device *wdd)
 {
        spin_lock(&io_lock);
 
-       __raw_writel(0, WDTIM_CTRL(wdt_base));  /*stop counter */
+       writel(0, WDTIM_CTRL(wdt_base));        /*stop counter */
 
        spin_unlock(&io_lock);
+       return 0;
 }
 
-static int pnx4008_wdt_open(struct inode *inode, struct file *file)
-{
-       int ret;
-
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       ret = clk_enable(wdt_clk);
-       if (ret) {
-               clear_bit(WDT_IN_USE, &wdt_status);
-               return ret;
-       }
-
-       wdt_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t pnx4008_wdt_write(struct file *file, const char *data,
-                                       size_t len, loff_t *ppos)
+static int pnx4008_wdt_set_timeout(struct watchdog_device *wdd,
+                                   unsigned int new_timeout)
 {
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_enable();
-       }
-
-       return len;
+       wdd->timeout = new_timeout;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
+static const struct watchdog_info pnx4008_wdt_ident = {
        .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
            WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
        .identity = "PNX4008 Watchdog",
 };
 
-static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_enable();
-               ret = 0;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, (int *)arg);
-               if (ret)
-                       break;
-
-               if (time <= 0 || time > MAX_HEARTBEAT) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               heartbeat = time;
-               wdt_enable();
-               /* Fall through */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-       }
-       return ret;
-}
-
-static int pnx4008_wdt_release(struct inode *inode, struct file *file)
-{
-       if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n");
-
-       wdt_disable();
-       clk_disable(wdt_clk);
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations pnx4008_wdt_fops = {
+static const struct watchdog_ops pnx4008_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = pnx4008_wdt_write,
-       .unlocked_ioctl = pnx4008_wdt_ioctl,
-       .open = pnx4008_wdt_open,
-       .release = pnx4008_wdt_release,
+       .start = pnx4008_wdt_start,
+       .stop = pnx4008_wdt_stop,
+       .set_timeout = pnx4008_wdt_set_timeout,
 };
 
-static struct miscdevice pnx4008_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &pnx4008_wdt_fops,
+static struct watchdog_device pnx4008_wdd = {
+       .info = &pnx4008_wdt_ident,
+       .ops = &pnx4008_wdt_ops,
+       .min_timeout = 1,
+       .max_timeout = MAX_HEARTBEAT,
 };
 
 static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
 {
-       int ret = 0, size;
+       struct resource *r;
+       int ret = 0;
 
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
 
-       printk(KERN_INFO MODULE_NAME
-               "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
-
-       wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (wdt_mem == NULL) {
-               printk(KERN_INFO MODULE_NAME
-                       "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-
-       size = resource_size(wdt_mem);
-
-       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
-               printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
-               return -ENOENT;
-       }
-       wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start);
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       wdt_base = devm_request_and_ioremap(&pdev->dev, r);
+       if (!wdt_base)
+               return -EADDRINUSE;
 
        wdt_clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(wdt_clk)) {
-               ret = PTR_ERR(wdt_clk);
-               release_mem_region(wdt_mem->start, size);
-               wdt_mem = NULL;
-               goto out;
-       }
+       if (IS_ERR(wdt_clk))
+               return PTR_ERR(wdt_clk);
 
        ret = clk_enable(wdt_clk);
-       if (ret) {
-               release_mem_region(wdt_mem->start, size);
-               wdt_mem = NULL;
-               clk_put(wdt_clk);
+       if (ret)
                goto out;
-       }
 
-       ret = misc_register(&pnx4008_wdt_miscdev);
+       pnx4008_wdd.timeout = heartbeat;
+       pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
+                       WDIOF_CARDRESET : 0;
+       watchdog_set_nowayout(&pnx4008_wdd, nowayout);
+
+       pnx4008_wdt_stop(&pnx4008_wdd); /* disable for now */
+
+       ret = watchdog_register_device(&pnx4008_wdd);
        if (ret < 0) {
-               printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
-               release_mem_region(wdt_mem->start, size);
-               wdt_mem = NULL;
-               clk_disable(wdt_clk);
-               clk_put(wdt_clk);
-       } else {
-               boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
-                   WDIOF_CARDRESET : 0;
-               wdt_disable();          /*disable for now */
-               clk_disable(wdt_clk);
-               set_bit(WDT_DEVICE_INITED, &wdt_status);
+               dev_err(&pdev->dev, "cannot register watchdog device\n");
+               goto disable_clk;
        }
 
+       dev_info(&pdev->dev, "PNX4008 Watchdog Timer: heartbeat %d sec\n",
+                       heartbeat);
+
+       return 0;
+
+disable_clk:
+       clk_disable(wdt_clk);
 out:
+       clk_put(wdt_clk);
        return ret;
 }
 
 static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
 {
-       misc_deregister(&pnx4008_wdt_miscdev);
+       watchdog_unregister_device(&pnx4008_wdd);
 
        clk_disable(wdt_clk);
        clk_put(wdt_clk);
 
-       if (wdt_mem) {
-               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
-               wdt_mem = NULL;
-       }
        return 0;
 }
 
@@ -337,15 +213,16 @@ static struct platform_driver platform_wdt_driver = {
 module_platform_driver(platform_wdt_driver);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
 MODULE_DESCRIPTION("PNX4008 Watchdog Driver");
 
-module_param(heartbeat, int, 0);
+module_param(heartbeat, uint, 0);
 MODULE_PARM_DESC(heartbeat,
                 "Watchdog heartbeat period in seconds from 1 to "
                 __MODULE_STRING(MAX_HEARTBEAT) ", default "
                 __MODULE_STRING(DEFAULT_HEARTBEAT));
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Set to 1 to keep watchdog running after device release");
 
index a7b5ad2a98bd4208466d82f70a1681bdca70e298..1b62a7dfcc95c743b97c085202ef233b46c34f82 100644 (file)
@@ -17,6 +17,8 @@
  * based on softdog.c by Alan Cox <alan@redhat.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -30,7 +32,6 @@
 #include <linux/init.h>
 #include <asm/mach-pnx833x/pnx833x.h>
 
-#define PFX "pnx833x: "
 #define WATCHDOG_TIMEOUT 30            /* 30 sec Maximum timeout */
 #define WATCHDOG_COUNT_FREQUENCY 68000000U /* Watchdog counts at 68MHZ. */
 #define        PNX_WATCHDOG_TIMEOUT    (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY)
@@ -54,8 +55,8 @@ module_param(pnx833x_wdt_timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default="
                        __MODULE_STRING(PNX_TIMEOUT_VALUE) "(30 seconds).");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -76,7 +77,7 @@ static void pnx833x_wdt_start(void)
        PNX833X_REG(PNX833X_CONFIG +
                                PNX833X_CONFIG_CPU_COUNTERS_CONTROL) |= 0x1;
 
-       printk(KERN_INFO PFX "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 }
 
 static void pnx833x_wdt_stop(void)
@@ -87,7 +88,7 @@ static void pnx833x_wdt_stop(void)
        PNX833X_REG(PNX833X_CONFIG +
                        PNX833X_CONFIG_CPU_COUNTERS_CONTROL) &= 0xFFFFFFFE;
 
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void pnx833x_wdt_ping(void)
@@ -113,7 +114,7 @@ static int pnx833x_wdt_open(struct inode *inode, struct file *file)
 
        pnx833x_wdt_ping();
 
-       printk(KERN_INFO "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 
        return nonseekable_open(inode, file);
 }
@@ -232,9 +233,6 @@ static struct notifier_block pnx833x_wdt_notifier = {
        .notifier_call = pnx833x_wdt_notify_sys,
 };
 
-static char banner[] __initdata =
-       KERN_INFO PFX "Hardware Watchdog Timer for PNX833x: Version 0.1\n";
-
 static int __init watchdog_init(void)
 {
        int ret, cause;
@@ -243,27 +241,25 @@ static int __init watchdog_init(void)
        cause = PNX833X_REG(PNX833X_RESET);
        /*If bit 31 is set then watchdog was cause of reset.*/
        if (cause & 0x80000000) {
-               printk(KERN_INFO PFX "The system was previously reset due to "
-                       "the watchdog firing - please investigate...\n");
+               pr_info("The system was previously reset due to the watchdog firing - please investigate...\n");
        }
 
        ret = register_reboot_notifier(&pnx833x_wdt_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                return ret;
        }
 
        ret = misc_register(&pnx833x_wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&pnx833x_wdt_notifier);
                return ret;
        }
 
-       printk(banner);
+       pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n");
+
        if (start_enabled)
                pnx833x_wdt_start();
 
index bf7bc8aa1c016fee830d5a1cbb2c6d949fa948ff..547353a50ebb017c77d8b5ea7f64bf0521377bd3 100644 (file)
@@ -17,6 +17,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>              /* For module specific items */
 #include <linux/moduleparam.h>         /* For new moduleparam's */
 #include <linux/types.h>               /* For standard types (like size_t) */
@@ -33,8 +35,6 @@
 
 #include <asm/mach-rc32434/integ.h>    /* For the Watchdog registers */
 
-#define PFX KBUILD_MODNAME ": "
-
 #define VERSION "1.0"
 
 static struct {
@@ -64,8 +64,8 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout value, in seconds (default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -78,8 +78,7 @@ static int rc32434_wdt_set(int new_timeout)
        int max_to = WTCOMP2SEC((u32)-1);
 
        if (new_timeout < 0 || new_timeout > max_to) {
-               printk(KERN_ERR PFX "timeout value must be between 0 and %d",
-                       max_to);
+               pr_err("timeout value must be between 0 and %d\n", max_to);
                return -EINVAL;
        }
        timeout = new_timeout;
@@ -119,7 +118,7 @@ static void rc32434_wdt_start(void)
        SET_BITS(wdt_reg->wtc, or, nand);
 
        spin_unlock(&rc32434_wdt_device.io_lock);
-       printk(KERN_INFO PFX "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 }
 
 static void rc32434_wdt_stop(void)
@@ -130,7 +129,7 @@ static void rc32434_wdt_stop(void)
        SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN);
 
        spin_unlock(&rc32434_wdt_device.io_lock);
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void rc32434_wdt_ping(void)
@@ -160,8 +159,7 @@ static int rc32434_wdt_release(struct inode *inode, struct file *file)
                rc32434_wdt_stop();
                module_put(THIS_MODULE);
        } else {
-               printk(KERN_CRIT PFX
-                       "device closed unexpectedly. WDT will not stop!\n");
+               pr_crit("device closed unexpectedly. WDT will not stop!\n");
                rc32434_wdt_ping();
        }
        clear_bit(0, &rc32434_wdt_device.inuse);
@@ -262,9 +260,6 @@ static struct miscdevice rc32434_wdt_miscdev = {
        .fops   = &rc32434_wdt_fops,
 };
 
-static char banner[] __devinitdata = KERN_INFO PFX
-               "Watchdog Timer version " VERSION ", timer margin: %d sec\n";
-
 static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
 {
        int ret;
@@ -272,13 +267,13 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res");
        if (!r) {
-               printk(KERN_ERR PFX "failed to retrieve resources\n");
+               pr_err("failed to retrieve resources\n");
                return -ENODEV;
        }
 
        wdt_reg = ioremap_nocache(r->start, resource_size(r));
        if (!wdt_reg) {
-               printk(KERN_ERR PFX "failed to remap I/O resources\n");
+               pr_err("failed to remap I/O resources\n");
                return -ENXIO;
        }
 
@@ -291,18 +286,18 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
         * if not reset to the default */
        if (rc32434_wdt_set(timeout)) {
                rc32434_wdt_set(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be between 0 and %d\n",
+               pr_info("timeout value must be between 0 and %d\n",
                        WTCOMP2SEC((u32)-1));
        }
 
        ret = misc_register(&rc32434_wdt_miscdev);
        if (ret < 0) {
-               printk(KERN_ERR PFX "failed to register watchdog device\n");
+               pr_err("failed to register watchdog device\n");
                goto unmap;
        }
 
-       printk(banner, timeout);
+       pr_info("Watchdog Timer version " VERSION ", timer margin: %d sec\n",
+               timeout);
 
        return 0;
 
index c7e17ceafa6aeca9b83f77edc41a4e372d068585..49e1b1c2135cdde2c00bfd37978c02d8ce62cfd1 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -189,7 +191,7 @@ static int __devinit riowd_probe(struct platform_device *op)
 
        p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME);
        if (!p->regs) {
-               printk(KERN_ERR PFX "Cannot map registers.\n");
+               pr_err("Cannot map registers\n");
                goto out_free;
        }
        /* Make miscdev useable right away */
@@ -197,12 +199,12 @@ static int __devinit riowd_probe(struct platform_device *op)
 
        err = misc_register(&riowd_miscdev);
        if (err) {
-               printk(KERN_ERR PFX "Cannot register watchdog misc device.\n");
+               pr_err("Cannot register watchdog misc device\n");
                goto out_iounmap;
        }
 
-       printk(KERN_INFO PFX "Hardware watchdog [%i minutes], "
-              "regs at %p\n", riowd_timeout, p->regs);
+       pr_info("Hardware watchdog [%i minutes], regs at %p\n",
+               riowd_timeout, p->regs);
 
        dev_set_drvdata(&op->dev, p);
        return 0;
index 404172f02c9bea73f2be2b523c979693e69679d1..04e5a6de47d72743b7010758f1c78230d416f221 100644 (file)
@@ -23,6 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 
 #include <plat/regs-watchdog.h>
 
-#define PFX "s3c2410-wdt: "
-
 #define CONFIG_S3C2410_WATCHDOG_ATBOOT         (0)
 #define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME   (15)
 
-static int nowayout    = WATCHDOG_NOWAYOUT;
+static bool nowayout   = WATCHDOG_NOWAYOUT;
 static int tmr_margin  = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
 static int tmr_atboot  = CONFIG_S3C2410_WATCHDOG_ATBOOT;
 static int soft_noboot;
@@ -59,7 +59,7 @@ static int debug;
 
 module_param(tmr_margin,  int, 0);
 module_param(tmr_atboot,  int, 0);
-module_param(nowayout,    int, 0);
+module_param(nowayout,   bool, 0);
 module_param(soft_noboot, int, 0);
 module_param(debug,      int, 0);
 
@@ -84,10 +84,11 @@ static DEFINE_SPINLOCK(wdt_lock);
 
 /* watchdog control routines */
 
-#define DBG(msg...) do { \
-       if (debug) \
-               printk(KERN_INFO msg); \
-       } while (0)
+#define DBG(fmt, ...)                                  \
+do {                                                   \
+       if (debug)                                      \
+               pr_info(fmt, ##__VA_ARGS__);            \
+} while (0)
 
 /* functions */
 
@@ -200,6 +201,8 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou
        writel(count, wdt_base + S3C2410_WTDAT);
        writel(wtcon, wdt_base + S3C2410_WTCON);
 
+       wdd->timeout = timeout;
+
        return 0;
 }
 
@@ -354,7 +357,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
        ret = s3c2410wdt_cpufreq_register();
        if (ret < 0) {
-               printk(KERN_ERR PFX "failed to register cpufreq\n");
+               pr_err("failed to register cpufreq\n");
                goto err_clk;
        }
 
@@ -483,8 +486,8 @@ static int s3c2410wdt_resume(struct platform_device *dev)
        writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
        writel(wtcon_save, wdt_base + S3C2410_WTCON);
 
-       printk(KERN_INFO PFX "watchdog %sabled\n",
-              (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
+       pr_info("watchdog %sabled\n",
+               (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
 
        return 0;
 }
@@ -518,12 +521,10 @@ static struct platform_driver s3c2410wdt_driver = {
 };
 
 
-static char banner[] __initdata =
-       KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
-
 static int __init watchdog_init(void)
 {
-       printk(banner);
+       pr_info("S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n");
+
        return platform_driver_register(&s3c2410wdt_driver);
 }
 
index 016245419fadb17eda3646152ab507ae1057440f..54984deb8561e220298af3442be548d943677264 100644 (file)
@@ -17,6 +17,9 @@
  *
  *     27/11/2000 Initial release
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -25,6 +28,7 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 #include <linux/timex.h>
@@ -66,7 +70,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
  */
 static int sa1100dog_release(struct inode *inode, struct file *file)
 {
-       printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
+       pr_crit("Device closed - timer will not stop\n");
        clear_bit(1, &sa1100wdt_users);
        return 0;
 }
@@ -169,9 +173,8 @@ static int __init sa1100dog_init(void)
 
        ret = misc_register(&sa1100dog_miscdev);
        if (ret == 0)
-               printk(KERN_INFO
-                       "SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
-                                               margin);
+               pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
+                       margin);
        return ret;
 }
 
index b01a30e5a66315ef809e5038f27aef4f40782a5a..25c7a3f9652d92781ea03468c369bf0ba746bbf5 100644 (file)
@@ -43,6 +43,9 @@
  *     version 1 or 2 as published by the Free Software Foundation.
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
@@ -125,9 +128,8 @@ static int sbwdog_release(struct inode *inode, struct file *file)
                __raw_writeb(0, user_dog);
                module_put(THIS_MODULE);
        } else {
-               printk(KERN_CRIT
-                       "%s: Unexpected close, not stopping watchdog!\n",
-                                               ident.identity);
+               pr_crit("%s: Unexpected close, not stopping watchdog!\n",
+                       ident.identity);
                sbwdog_pet(user_dog);
        }
        clear_bit(0, &sbwdog_gate);
@@ -269,7 +271,7 @@ irqreturn_t sbwdog_interrupt(int irq, void *addr)
         * if it's the second watchdog timer, it's for those users
         */
        if (wd_cfg_reg == user_dog)
-               printk(KERN_CRIT "%s in danger of initiating system reset "
+               pr_crit("%s in danger of initiating system reset "
                        "in %ld.%01ld seconds\n",
                        ident.identity,
                        wd_init / 1000000, (wd_init / 100000) % 10);
@@ -290,9 +292,8 @@ static int __init sbwdog_init(void)
         */
        ret = register_reboot_notifier(&sbwdog_notifier);
        if (ret) {
-               printk(KERN_ERR
-                       "%s: cannot register reboot notifier (err=%d)\n",
-                                               ident.identity, ret);
+               pr_err("%s: cannot register reboot notifier (err=%d)\n",
+                      ident.identity, ret);
                return ret;
        }
 
@@ -303,16 +304,16 @@ static int __init sbwdog_init(void)
        ret = request_irq(1, sbwdog_interrupt, IRQF_SHARED,
                ident.identity, (void *)user_dog);
        if (ret) {
-               printk(KERN_ERR "%s: failed to request irq 1 - %d\n",
-                                               ident.identity, ret);
+               pr_err("%s: failed to request irq 1 - %d\n",
+                      ident.identity, ret);
                goto out;
        }
 
        ret = misc_register(&sbwdog_miscdev);
        if (ret == 0) {
-               printk(KERN_INFO "%s: timeout is %ld.%ld secs\n",
-                               ident.identity,
-                               timeout / 1000000, (timeout / 100000) % 10);
+               pr_info("%s: timeout is %ld.%ld secs\n",
+                       ident.identity,
+                       timeout / 1000000, (timeout / 100000) % 10);
                return 0;
        }
        free_irq(1, (void *)user_dog);
@@ -353,8 +354,7 @@ void platform_wd_setup(void)
        ret = request_irq(1, sbwdog_interrupt, IRQF_SHARED,
                "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0));
        if (ret) {
-               printk(KERN_CRIT
-                 "Watchdog IRQ zero(0) failed to be requested - %d\n", ret);
+               pr_crit("Watchdog IRQ zero(0) failed to be requested - %d\n", ret);
        }
 }
 
index 626d0e8e56c390c48bb12301208f56fec3715c15..63632ec87c7e7f7064485521a9fa3109b61c7740 100644 (file)
@@ -48,6 +48,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -63,7 +65,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define OUR_NAME "sbc60xxwdt"
 #define PFX OUR_NAME ": "
@@ -105,8 +106,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. (1<=timeout<=3600, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -132,8 +133,7 @@ static void wdt_timer_ping(unsigned long data)
                /* Re-set the timer interval */
                mod_timer(&timer, jiffies + WDT_INTERVAL);
        } else
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
 }
 
 /*
@@ -146,7 +146,7 @@ static void wdt_startup(void)
 
        /* Start the timer */
        mod_timer(&timer, jiffies + WDT_INTERVAL);
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 static void wdt_turnoff(void)
@@ -154,7 +154,7 @@ static void wdt_turnoff(void)
        /* Stop the timer */
        del_timer(&timer);
        inb_p(wdt_stop);
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
 }
 
 static void wdt_keepalive(void)
@@ -217,8 +217,7 @@ static int fop_close(struct inode *inode, struct file *file)
                wdt_turnoff();
        else {
                del_timer(&timer);
-               printk(KERN_CRIT PFX
-                 "device file closed unexpectedly. Will not stop the WDT!\n");
+               pr_crit("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &wdt_is_open);
        wdt_expect_close = 0;
@@ -335,14 +334,12 @@ static int __init sbc60xxwdt_init(void)
 
        if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 3600, using %d\n",
-                                                               timeout);
+               pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
+                       timeout);
        }
 
        if (!request_region(wdt_start, 1, "SBC 60XX WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                rc = -EIO;
                goto err_out;
        }
@@ -350,9 +347,7 @@ static int __init sbc60xxwdt_init(void)
        /* We cannot reserve 0x45 - the kernel already has! */
        if (wdt_stop != 0x45 && wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                       wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n", wdt_stop);
                        rc = -EIO;
                        goto err_out_region1;
                }
@@ -360,21 +355,18 @@ static int __init sbc60xxwdt_init(void)
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region2;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
-       printk(KERN_INFO PFX
-               "WDT driver for 60XX single board computer initialised. "
-               "timeout=%d sec (nowayout=%d)\n", timeout, nowayout);
+       pr_info("WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
        return 0;
 
index 93ac58953122c67d55e63a6056b14357d8db8cfb..719edc8fdeb39c083d797fa72010b79bb50e728b 100644 (file)
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -30,9 +32,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
-
-#define SBC7240_PREFIX "sbc7240_wdt: "
 
 #define SBC7240_ENABLE_PORT            0x443
 #define SBC7240_DISABLE_PORT           0x043
@@ -47,8 +46,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<="
                 __MODULE_STRING(SBC7240_MAX_TIMEOUT) ", default="
                 __MODULE_STRING(SBC7240_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog when closing device file");
 
 #define SBC7240_OPEN_STATUS_BIT                0
@@ -65,8 +64,7 @@ static void wdt_disable(void)
        /* disable the watchdog */
        if (test_and_clear_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) {
                inb_p(SBC7240_DISABLE_PORT);
-               printk(KERN_INFO SBC7240_PREFIX
-                      "Watchdog timer is now disabled.\n");
+               pr_info("Watchdog timer is now disabled\n");
        }
 }
 
@@ -75,23 +73,20 @@ static void wdt_enable(void)
        /* enable the watchdog */
        if (!test_and_set_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) {
                inb_p(SBC7240_ENABLE_PORT);
-               printk(KERN_INFO SBC7240_PREFIX
-                      "Watchdog timer is now enabled.\n");
+               pr_info("Watchdog timer is now enabled\n");
        }
 }
 
 static int wdt_set_timeout(int t)
 {
        if (t < 1 || t > SBC7240_MAX_TIMEOUT) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "timeout value must be 1<=x<=%d\n",
-                      SBC7240_MAX_TIMEOUT);
+               pr_err("timeout value must be 1<=x<=%d\n", SBC7240_MAX_TIMEOUT);
                return -1;
        }
        /* set the timeout */
        outb_p((unsigned)t, SBC7240_SET_TIMEOUT_PORT);
        timeout = t;
-       printk(KERN_INFO SBC7240_PREFIX "timeout set to %d seconds\n", t);
+       pr_info("timeout set to %d seconds\n", t);
        return 0;
 }
 
@@ -150,8 +145,7 @@ static int fop_close(struct inode *inode, struct file *file)
            || !nowayout) {
                wdt_disable();
        } else {
-               printk(KERN_CRIT SBC7240_PREFIX
-                      "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_keepalive();
        }
 
@@ -252,7 +246,7 @@ static struct notifier_block wdt_notifier = {
 
 static void __exit sbc7240_wdt_unload(void)
 {
-       printk(KERN_INFO SBC7240_PREFIX "Removing watchdog\n");
+       pr_info("Removing watchdog\n");
        misc_deregister(&wdt_miscdev);
 
        unregister_reboot_notifier(&wdt_notifier);
@@ -264,8 +258,7 @@ static int __init sbc7240_wdt_init(void)
        int rc = -EBUSY;
 
        if (!request_region(SBC7240_ENABLE_PORT, 1, "SBC7240 WDT")) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "I/O address 0x%04x already in use\n",
+               pr_err("I/O address 0x%04x already in use\n",
                       SBC7240_ENABLE_PORT);
                rc = -EIO;
                goto err_out;
@@ -277,31 +270,27 @@ static int __init sbc7240_wdt_init(void)
 
        if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) {
                timeout = SBC7240_TIMEOUT;
-               printk(KERN_INFO SBC7240_PREFIX
-                      "timeout value must be 1<=x<=%d, using %d\n",
-                      SBC7240_MAX_TIMEOUT, timeout);
+               pr_info("timeout value must be 1<=x<=%d, using %d\n",
+                       SBC7240_MAX_TIMEOUT, timeout);
        }
        wdt_set_timeout(timeout);
        wdt_disable();
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "cannot register miscdev on minor=%d (err=%d)\n",
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
                       wdt_miscdev.minor, rc);
                goto err_out_reboot_notifier;
        }
 
-       printk(KERN_INFO SBC7240_PREFIX
-              "Watchdog driver for SBC7240 initialised (nowayout=%d)\n",
-              nowayout);
+       pr_info("Watchdog driver for SBC7240 initialised (nowayout=%d)\n",
+               nowayout);
 
        return 0;
 
index 514ec23050f7814565a209649c809f0763426151..d4781e05f0171bbe577f95d524445362db59624a 100644 (file)
@@ -36,6 +36,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 static unsigned long sbc8360_is_open;
 static char expect_close;
 
-#define PFX "sbc8360: "
-
 /*
  *
  * Watchdog Timer Configuration
@@ -197,11 +196,11 @@ static int wd_times[64][2] = {
 static int timeout = 27;
 static int wd_margin = 0xB;
 static int wd_multiplier = 2;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -280,8 +279,7 @@ static int sbc8360_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                sbc8360_stop();
        else
-               printk(KERN_CRIT PFX "SBC8360 device closed unexpectedly.  "
-                                               "SBC8360 will not stop!\n");
+               pr_crit("SBC8360 device closed unexpectedly.  SBC8360 will not stop!\n");
 
        clear_bit(0, &sbc8360_is_open);
        expect_close = 0;
@@ -334,20 +332,19 @@ static int __init sbc8360_init(void)
        unsigned long int mseconds = 60000;
 
        if (timeout < 0 || timeout > 63) {
-               printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+               pr_err("Invalid timeout index (must be 0-63)\n");
                res = -EINVAL;
                goto out;
        }
 
        if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
-               printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+               pr_err("ENABLE method I/O %X is not available\n",
                       SBC8360_ENABLE);
                res = -EIO;
                goto out;
        }
        if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
-               printk(KERN_ERR PFX
-                      "BASETIME method I/O %X is not available.\n",
+               pr_err("BASETIME method I/O %X is not available\n",
                       SBC8360_BASETIME);
                res = -EIO;
                goto out_nobasetimereg;
@@ -355,13 +352,13 @@ static int __init sbc8360_init(void)
 
        res = register_reboot_notifier(&sbc8360_notifier);
        if (res) {
-               printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+               pr_err("Failed to register reboot notifier\n");
                goto out_noreboot;
        }
 
        res = misc_register(&sbc8360_miscdev);
        if (res) {
-               printk(KERN_ERR PFX "failed to register misc device\n");
+               pr_err("failed to register misc device\n");
                goto out_nomisc;
        }
 
@@ -378,7 +375,7 @@ static int __init sbc8360_init(void)
                mseconds = (wd_margin + 1) * 100000;
 
        /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
-       printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+       pr_info("Timeout set at %ld ms\n", mseconds);
 
        return 0;
 
index eaca366b7234a5c1df978adcaacd73a01a66337b..0c3e9f66ef7713bc88e37c48353fb646197f9ff8 100644 (file)
@@ -13,6 +13,8 @@
  *     based on softdog.c by Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#define PFX "epx_c3: "
 static int epx_c3_alive;
 
 #define WATCHDOG_TIMEOUT 1             /* 1 sec default timeout */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -51,7 +52,7 @@ static void epx_c3_stop(void)
 
        outb(0, EPXC3_WATCHDOG_CTL_REG);
 
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void epx_c3_pet(void)
@@ -75,7 +76,7 @@ static int epx_c3_open(struct inode *inode, struct file *file)
        epx_c3_pet();
 
        epx_c3_alive = 1;
-       printk(KERN_INFO "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 
        return nonseekable_open(inode, file);
 }
@@ -173,9 +174,6 @@ static struct notifier_block epx_c3_notifier = {
        .notifier_call = epx_c3_notify_sys,
 };
 
-static const char banner[] __initconst = KERN_INFO PFX
-       "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
-
 static int __init watchdog_init(void)
 {
        int ret;
@@ -185,20 +183,19 @@ static int __init watchdog_init(void)
 
        ret = register_reboot_notifier(&epx_c3_notifier);
        if (ret) {
-               printk(KERN_ERR PFX "cannot register reboot notifier "
-                       "(err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto out;
        }
 
        ret = misc_register(&epx_c3_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
-                       "(err=%d)\n", WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&epx_c3_notifier);
                goto out;
        }
 
-       printk(banner);
+       pr_info("Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n");
 
        return 0;
 
index d5d399464599f3dcc43accc1ba861ee5bc24a1d8..90d5527ca8863663cbd951ae2a656423eff3fb1e 100644 (file)
@@ -25,9 +25,8 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int margin = 60;       /* (secs) Default is 1 minute */
 static unsigned long wdt_status;
 static DEFINE_MUTEX(wdt_lock);
@@ -171,8 +170,7 @@ static int fitpc2_wdt_release(struct inode *inode, struct file *file)
                wdt_disable();
                pr_info("Device disabled\n");
        } else {
-               pr_warning("Device closed unexpectedly -"
-                       " timer will not stop\n");
+               pr_warn("Device closed unexpectedly - timer will not stop\n");
                wdt_enable();
        }
 
@@ -222,8 +220,8 @@ static int __init fitpc2_wdt_init(void)
        }
 
        if (margin < 31 || margin > 255) {
-               pr_err("margin must be in range 31 - 255"
-                      " seconds, you tried to set %d\n", margin);
+               pr_err("margin must be in range 31 - 255 seconds, you tried to set %d\n",
+                      margin);
                err = -EINVAL;
                goto err_margin;
        }
@@ -231,7 +229,7 @@ static int __init fitpc2_wdt_init(void)
        err = misc_register(&fitpc2_wdt_miscdev);
        if (err) {
                pr_err("cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, err);
+                      WATCHDOG_MINOR, err);
                goto err_margin;
        }
 
@@ -261,7 +259,7 @@ MODULE_DESCRIPTION("SBC-FITPC2 Watchdog");
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index c01daca8405a46ccb53ff54d5c03771e363bf5ad..3fb83b0c28c23a58862b55f482ed2e8c3c0003c9 100644 (file)
@@ -31,6 +31,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/miscdevice.h>
@@ -48,7 +50,6 @@
 
 #define SC1200_MODULE_VER      "build 20020303"
 #define SC1200_MODULE_NAME     "sc1200wdt"
-#define PFX                    SC1200_MODULE_NAME ": "
 
 #define        MAX_TIMEOUT     255     /* 255 minutes */
 #define PMIR           (io)    /* Power Management Index Register */
@@ -71,7 +72,6 @@
 #define UART2_IRQ      0x04    /* Serial1 */
 /* 5 -7 are reserved */
 
-static char banner[] __initdata = PFX SC1200_MODULE_VER;
 static int timeout = 1;
 static int io = -1;
 static int io_len = 2;         /* for non plug and play */
@@ -93,8 +93,8 @@ MODULE_PARM_DESC(io, "io port");
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -176,7 +176,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file)
                timeout = MAX_TIMEOUT;
 
        sc1200wdt_start();
-       printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout);
+       pr_info("Watchdog enabled, timeout = %d min(s)", timeout);
 
        return nonseekable_open(inode, file);
 }
@@ -254,11 +254,10 @@ static int sc1200wdt_release(struct inode *inode, struct file *file)
 {
        if (expect_close == 42) {
                sc1200wdt_stop();
-               printk(KERN_INFO PFX "Watchdog disabled\n");
+               pr_info("Watchdog disabled\n");
        } else {
                sc1200wdt_write_data(WDTO, timeout);
-               printk(KERN_CRIT PFX
-                       "Unexpected close!, timeout = %d min(s)\n", timeout);
+               pr_crit("Unexpected close!, timeout = %d min(s)\n", timeout);
        }
        clear_bit(0, &open_flag);
        expect_close = 0;
@@ -361,12 +360,11 @@ static int scl200wdt_pnp_probe(struct pnp_dev *dev,
        io_len = pnp_port_len(wdt_dev, 0);
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
-               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
+               pr_err("Unable to register IO port %#x\n", io);
                return -EBUSY;
        }
 
-       printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n",
-                                                               io, io_len);
+       pr_info("PnP device found at io port %#x/%d\n", io, io_len);
        return 0;
 }
 
@@ -392,7 +390,7 @@ static int __init sc1200wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "%s\n", banner);
+       pr_info("%s\n", SC1200_MODULE_VER);
 
 #if defined CONFIG_PNP
        if (isapnp) {
@@ -403,7 +401,7 @@ static int __init sc1200wdt_init(void)
 #endif
 
        if (io == -1) {
-               printk(KERN_ERR PFX "io parameter must be specified\n");
+               pr_err("io parameter must be specified\n");
                ret = -EINVAL;
                goto out_pnp;
        }
@@ -416,7 +414,7 @@ static int __init sc1200wdt_init(void)
 #endif
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
-               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
+               pr_err("Unable to register IO port %#x\n", io);
                ret = -EBUSY;
                goto out_pnp;
        }
@@ -427,16 +425,14 @@ static int __init sc1200wdt_init(void)
 
        ret = register_reboot_notifier(&sc1200wdt_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "Unable to register reboot notifier err = %d\n", ret);
+               pr_err("Unable to register reboot notifier err = %d\n", ret);
                goto out_io;
        }
 
        ret = misc_register(&sc1200wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "Unable to register miscdev on minor %d\n",
-                                                       WATCHDOG_MINOR);
+               pr_err("Unable to register miscdev on minor %d\n",
+                      WATCHDOG_MINOR);
                goto out_rbt;
        }
 
index b2840409ebc72ca5ba6a6f30dc96bc12b00f7b73..707e027e50025f4fbff1c73215ede8a3ee4491df 100644 (file)
@@ -52,6 +52,8 @@
  *  This driver uses memory mapped IO, and spinlock.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
-
-#define OUR_NAME "sc520_wdt"
-#define PFX OUR_NAME ": "
 
 /*
  * The AMD Elan SC520 timeout value is 492us times a power of 2 (0-7)
@@ -98,8 +96,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. (1 <= timeout <= 3600, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -151,8 +149,7 @@ static void wdt_timer_ping(unsigned long data)
                /* Re-set the timer interval */
                mod_timer(&timer, jiffies + WDT_INTERVAL);
        } else
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
 }
 
 /*
@@ -187,7 +184,7 @@ static int wdt_startup(void)
        /* Start the watchdog */
        wdt_config(WDT_ENB | WDT_WRST_ENB | WDT_EXP_SEL_04);
 
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
        return 0;
 }
 
@@ -199,7 +196,7 @@ static int wdt_turnoff(void)
        /* Stop the watchdog */
        wdt_config(0);
 
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
        return 0;
 }
 
@@ -270,8 +267,7 @@ static int fop_close(struct inode *inode, struct file *file)
        if (wdt_expect_close == 42)
                wdt_turnoff();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_keepalive();
        }
        clear_bit(0, &wdt_is_open);
@@ -393,36 +389,32 @@ static int __init sc520_wdt_init(void)
           if not reset to the default */
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                   "timeout value must be 1 <= timeout <= 3600, using %d\n",
-                                                       WATCHDOG_TIMEOUT);
+               pr_info("timeout value must be 1 <= timeout <= 3600, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        wdtmrctl = ioremap(MMCR_BASE + OFFS_WDTMRCTL, 2);
        if (!wdtmrctl) {
-               printk(KERN_ERR PFX "Unable to remap memory\n");
+               pr_err("Unable to remap memory\n");
                rc = -ENOMEM;
                goto err_out_region2;
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_ioremap;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, rc);
                goto err_out_notifier;
        }
 
-       printk(KERN_INFO PFX
-          "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
-                                                       timeout, nowayout);
+       pr_info("WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
        return 0;
 
index 029467e34636f6b057e3c93ac5bdf7b524de945c..bd86f32d63ab8dc5f5f57d80f55dd4fbb7dcb6bd 100644 (file)
@@ -18,6 +18,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
 #include <linux/moduleparam.h>         /* For new moduleparam's */
@@ -37,7 +39,6 @@
 
 /* Module and version information */
 #define DRV_NAME       "sch311x_wdt"
-#define PFX            DRV_NAME ": "
 
 /* Runtime registers */
 #define RESGEN                 0x1d
@@ -79,8 +80,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=15300, default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -323,8 +324,7 @@ static int sch311x_wdt_close(struct inode *inode, struct file *file)
        if (sch311x_wdt_expect_close == 42) {
                sch311x_wdt_stop();
        } else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                sch311x_wdt_keepalive();
        }
        clear_bit(0, &sch311x_wdt_is_open);
@@ -504,20 +504,19 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
 
        /* Check if Logical Device Register is currently active */
        if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0)
-               printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n");
+               pr_info("Seems that LDN 0x0a is not active...\n");
 
        /* Get the base address of the runtime registers */
        base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) |
                           sch311x_sio_inb(sio_config_port, 0x61);
        if (!base_addr) {
-               printk(KERN_ERR PFX "Base address not set.\n");
+               pr_err("Base address not set\n");
                err = -ENODEV;
                goto exit;
        }
        *addr = base_addr;
 
-       printk(KERN_INFO PFX "Found an SMSC SCH311%d chip at 0x%04x\n",
-               dev_id, base_addr);
+       pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr);
 
 exit:
        sch311x_sio_exit(sio_config_port);
index e67b76c0526c340f80ddba05e978b0bd46e15844..8ae7c282d465ade3be2c3f08efe91968bf2bb503 100644 (file)
@@ -17,6 +17,8 @@
    of any nature resulting due to the use of this software. This
    software is provided AS-IS with no warranties. */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -30,7 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#define NAME "scx200_wdt"
+#define DEBUG
 
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
@@ -41,8 +43,8 @@ static int margin = 60;               /* in seconds */
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 static u16 wdto_restart;
@@ -66,14 +68,13 @@ static void scx200_wdt_ping(void)
 
 static void scx200_wdt_update_margin(void)
 {
-       printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
+       pr_info("timer margin %d seconds\n", margin);
        wdto_restart = margin * W_SCALE;
 }
 
 static void scx200_wdt_enable(void)
 {
-       printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
-              wdto_restart);
+       pr_debug("enabling watchdog timer, wdto_restart = %d\n", wdto_restart);
 
        spin_lock(&scx_lock);
        outw(0, scx200_cb_base + SCx200_WDT_WDTO);
@@ -86,7 +87,7 @@ static void scx200_wdt_enable(void)
 
 static void scx200_wdt_disable(void)
 {
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+       pr_debug("disabling watchdog timer\n");
 
        spin_lock(&scx_lock);
        outw(0, scx200_cb_base + SCx200_WDT_WDTO);
@@ -108,9 +109,7 @@ static int scx200_wdt_open(struct inode *inode, struct file *file)
 static int scx200_wdt_release(struct inode *inode, struct file *file)
 {
        if (expect_close != 42)
-               printk(KERN_WARNING NAME
-                       ": watchdog device closed unexpectedly, "
-                       "will not disable the watchdog timer\n");
+               pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer\n");
        else if (!nowayout)
                scx200_wdt_disable();
        expect_close = 0;
@@ -219,7 +218,7 @@ static int __init scx200_wdt_init(void)
 {
        int r;
 
-       printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
+       pr_debug("NatSemi SCx200 Watchdog Driver\n");
 
        /* check that we have found the configuration block */
        if (!scx200_cb_present())
@@ -228,7 +227,7 @@ static int __init scx200_wdt_init(void)
        if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
                            SCx200_WDT_SIZE,
                            "NatSemi SCx200 Watchdog")) {
-               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+               pr_warn("watchdog I/O region busy\n");
                return -EBUSY;
        }
 
@@ -237,7 +236,7 @@ static int __init scx200_wdt_init(void)
 
        r = register_reboot_notifier(&scx200_wdt_notifier);
        if (r) {
-               printk(KERN_ERR NAME ": unable to register reboot notifier");
+               pr_err("unable to register reboot notifier\n");
                release_region(scx200_cb_base + SCx200_WDT_OFFSET,
                                SCx200_WDT_SIZE);
                return r;
index a267dc078dafb777f6855a56aef73ae48c1228f5..93958a7763e69d00941fab2de25448c04cead8f9 100644 (file)
@@ -17,6 +17,9 @@
  *     Added expect close support, made emulated timeout runtime changeable
  *     general cleanups, add some ioctls
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
@@ -72,7 +75,7 @@ static DEFINE_SPINLOCK(shwdt_lock);
 
 #define WATCHDOG_HEARTBEAT 30                  /* 30 sec default heartbeat */
 static int heartbeat = WATCHDOG_HEARTBEAT;     /* in seconds */
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned long next_heartbeat;
 
 struct sh_wdt {
@@ -440,20 +443,20 @@ static int __init sh_wdt_init(void)
                     clock_division_ratio > 0x7)) {
                clock_division_ratio = WTCSR_CKS_4096;
 
-               pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n",
-                        DRV_NAME, clock_division_ratio);
+               pr_info("divisor must be 0x5<=x<=0x7, using %d\n",
+                       clock_division_ratio);
        }
 
        rc = sh_wdt_set_heartbeat(heartbeat);
        if (unlikely(rc)) {
                heartbeat = WATCHDOG_HEARTBEAT;
 
-               pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
-                       DRV_NAME, heartbeat);
+               pr_info("heartbeat value must be 1<=x<=3600, using %d\n",
+                       heartbeat);
        }
 
-       pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
-               DRV_NAME, heartbeat, nowayout);
+       pr_info("configured with heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
 
        return platform_driver_register(&sh_wdt_driver);
 }
@@ -481,7 +484,7 @@ MODULE_PARM_DESC(heartbeat,
        "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 97b8184614ae6b0956a873ec50cb955a731b8553..6d665f9c1d586393224594df0d2ae57bd9412b29 100644 (file)
@@ -43,6 +43,8 @@
  *   Documentation/watchdog/wdt.txt
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -58,7 +60,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 /* enable support for minutes as units? */
 /* (does not always work correctly, so disabled by default!) */
@@ -70,7 +71,6 @@
 #define UNIT_SECOND     0
 #define UNIT_MINUTE     1
 
-#define MODNAME                "smsc37b787_wdt: "
 #define VERSION                "1.1"
 
 #define IOPORT         0x3F0
@@ -85,7 +85,7 @@ static char expect_close;       /* is the close expected? */
 
 static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* -- Low level function ----------------------------------------*/
 
@@ -363,8 +363,7 @@ static int wb_smsc_wdt_open(struct inode *inode, struct file *file)
        /* Reload and activate timer */
        wb_smsc_wdt_enable();
 
-       printk(KERN_INFO MODNAME
-               "Watchdog enabled. Timeout set to %d %s.\n",
+       pr_info("Watchdog enabled. Timeout set to %d %s\n",
                timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
 
        return nonseekable_open(inode, file);
@@ -378,11 +377,9 @@ static int wb_smsc_wdt_release(struct inode *inode, struct file *file)
 
        if (expect_close == 42) {
                wb_smsc_wdt_disable();
-               printk(KERN_INFO MODNAME
-                               "Watchdog disabled, sleeping again...\n");
+               pr_info("Watchdog disabled, sleeping again...\n");
        } else {
-               printk(KERN_CRIT MODNAME
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wb_smsc_wdt_reset_timer();
        }
 
@@ -534,12 +531,11 @@ static int __init wb_smsc_wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "SMsC 37B787 watchdog component driver "
-                                       VERSION " initialising...\n");
+       pr_info("SMsC 37B787 watchdog component driver "
+               VERSION " initialising...\n");
 
        if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
-               printk(KERN_ERR MODNAME "Unable to register IO port %#x\n",
-                                                               IOPORT);
+               pr_err("Unable to register IO port %#x\n", IOPORT);
                ret = -EBUSY;
                goto out_pnp;
        }
@@ -553,25 +549,22 @@ static int __init wb_smsc_wdt_init(void)
 
        ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
        if (ret) {
-               printk(KERN_ERR MODNAME
-                       "Unable to register reboot notifier err = %d\n", ret);
+               pr_err("Unable to register reboot notifier err = %d\n", ret);
                goto out_io;
        }
 
        ret = misc_register(&wb_smsc_wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR MODNAME
-                       "Unable to register miscdev on minor %d\n",
-                                                       WATCHDOG_MINOR);
+               pr_err("Unable to register miscdev on minor %d\n",
+                      WATCHDOG_MINOR);
                goto out_rbt;
        }
 
        /* output info */
-       printk(KERN_INFO MODNAME "Timeout set to %d %s.\n",
+       pr_info("Timeout set to %d %s\n",
                timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
-       printk(KERN_INFO MODNAME
-               "Watchdog initialized and sleeping (nowayout=%d)...\n",
-                                                               nowayout);
+       pr_info("Watchdog initialized and sleeping (nowayout=%d)...\n",
+               nowayout);
 out_clean:
        return ret;
 
@@ -592,14 +585,14 @@ static void __exit wb_smsc_wdt_exit(void)
        /* Stop the timer before we leave */
        if (!nowayout) {
                wb_smsc_wdt_shutdown();
-               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+               pr_info("Watchdog disabled\n");
        }
 
        misc_deregister(&wb_smsc_wdt_miscdev);
        unregister_reboot_notifier(&wb_smsc_wdt_notifier);
        release_region(IOPORT, IOPORT_SIZE);
 
-       printk(KERN_INFO "SMsC 37B787 watchdog component driver removed.\n");
+       pr_info("SMsC 37B787 watchdog component driver removed\n");
 }
 
 module_init(wb_smsc_wdt_init);
@@ -621,7 +614,7 @@ MODULE_PARM_DESC(unit,
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index bf16ffb4d21e122b48c6b63075c235573bf7c159..fe83beb8f1b7c3f5a0c6b679f209145df77e644f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     SoftDog 0.07:   A Software Watchdog Device
+ *     SoftDog:        A Software Watchdog Device
  *
  *     (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
  *                                                     All Rights Reserved.
  *     Added Matt Domsch's nowayout module option.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/fs.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
-#include <linux/uaccess.h>
 #include <linux/kernel.h>
 
-#define PFX "SoftDog: "
-
 #define TIMER_MARGIN   60              /* Default is 60 seconds */
-static int soft_margin = TIMER_MARGIN; /* in seconds */
-module_param(soft_margin, int, 0);
+static unsigned int soft_margin = TIMER_MARGIN;        /* in seconds */
+module_param(soft_margin, uint, 0);
 MODULE_PARM_DESC(soft_margin,
        "Watchdog soft_margin in seconds. (0 < soft_margin < 65536, default="
                                        __MODULE_STRING(TIMER_MARGIN) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-#ifdef ONLY_TESTING
-static int soft_noboot = 1;
-#else
 static int soft_noboot = 0;
-#endif  /* ONLY_TESTING */
-
 module_param(soft_noboot, int, 0);
 MODULE_PARM_DESC(soft_noboot,
-       "Softdog action, set to 1 to ignore reboots, 0 to reboot "
-                                       "(default depends on ONLY_TESTING)");
+       "Softdog action, set to 1 to ignore reboots, 0 to reboot (default=0)");
 
 static int soft_panic;
 module_param(soft_panic, int, 0);
@@ -89,9 +81,6 @@ static void watchdog_fire(unsigned long);
 
 static struct timer_list watchdog_ticktock =
                TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static unsigned long driver_open, orphan_timer;
-static char expect_close;
-
 
 /*
  *     If the timer expires..
@@ -99,18 +88,15 @@ static char expect_close;
 
 static void watchdog_fire(unsigned long data)
 {
-       if (test_and_clear_bit(0, &orphan_timer))
-               module_put(THIS_MODULE);
-
        if (soft_noboot)
-               printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
+               pr_crit("Triggered - Reboot ignored\n");
        else if (soft_panic) {
-               printk(KERN_CRIT PFX "Initiating panic.\n");
-               panic("Software Watchdog Timer expired.");
+               pr_crit("Initiating panic\n");
+               panic("Software Watchdog Timer expired");
        } else {
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart();
-               printk(KERN_CRIT PFX "Reboot didn't ?????\n");
+               pr_crit("Reboot didn't ?????\n");
        }
 }
 
@@ -118,127 +104,24 @@ static void watchdog_fire(unsigned long data)
  *     Softdog operations
  */
 
-static int softdog_keepalive(void)
+static int softdog_ping(struct watchdog_device *w)
 {
-       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+       mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ));
        return 0;
 }
 
-static int softdog_stop(void)
+static int softdog_stop(struct watchdog_device *w)
 {
        del_timer(&watchdog_ticktock);
        return 0;
 }
 
-static int softdog_set_heartbeat(int t)
-{
-       if ((t < 0x0001) || (t > 0xFFFF))
-               return -EINVAL;
-
-       soft_margin = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int softdog_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &driver_open))
-               return -EBUSY;
-       if (!test_and_clear_bit(0, &orphan_timer))
-               __module_get(THIS_MODULE);
-       /*
-        *      Activate timer
-        */
-       softdog_keepalive();
-       return nonseekable_open(inode, file);
-}
-
-static int softdog_release(struct inode *inode, struct file *file)
+static int softdog_set_timeout(struct watchdog_device *w, unsigned int t)
 {
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if (expect_close == 42) {
-               softdog_stop();
-               module_put(THIS_MODULE);
-       } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
-               set_bit(0, &orphan_timer);
-               softdog_keepalive();
-       }
-       clear_bit(0, &driver_open);
-       expect_close = 0;
+       w->timeout = t;
        return 0;
 }
 
-static ssize_t softdog_write(struct file *file, const char __user *data,
-                                               size_t len, loff_t *ppos)
-{
-       /*
-        *      Refresh the timer.
-        */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               softdog_keepalive();
-       }
-       return len;
-}
-
-static long softdog_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_margin;
-       static const struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "Software Watchdog",
-       };
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-       case WDIOC_KEEPALIVE:
-               softdog_keepalive();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, p))
-                       return -EFAULT;
-               if (softdog_set_heartbeat(new_margin))
-                       return -EINVAL;
-               softdog_keepalive();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(soft_margin, p);
-       default:
-               return -ENOTTY;
-       }
-}
-
 /*
  *     Notifier for system down
  */
@@ -248,7 +131,7 @@ static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
 {
        if (code == SYS_DOWN || code == SYS_HALT)
                /* Turn the WDT off */
-               softdog_stop();
+               softdog_stop(NULL);
        return NOTIFY_DONE;
 }
 
@@ -256,28 +139,29 @@ static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
  *     Kernel Interfaces
  */
 
-static const struct file_operations softdog_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = softdog_write,
-       .unlocked_ioctl = softdog_ioctl,
-       .open           = softdog_open,
-       .release        = softdog_release,
+static struct notifier_block softdog_notifier = {
+       .notifier_call  = softdog_notify_sys,
 };
 
-static struct miscdevice softdog_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &softdog_fops,
+static struct watchdog_info softdog_info = {
+       .identity = "Software Watchdog",
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 };
 
-static struct notifier_block softdog_notifier = {
-       .notifier_call  = softdog_notify_sys,
+static struct watchdog_ops softdog_ops = {
+       .owner = THIS_MODULE,
+       .start = softdog_ping,
+       .stop = softdog_stop,
+       .ping = softdog_ping,
+       .set_timeout = softdog_set_timeout,
 };
 
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 "
-       "initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d "
-       "(nowayout= %d)\n";
+static struct watchdog_device softdog_dev = {
+       .info = &softdog_info,
+       .ops = &softdog_ops,
+       .min_timeout = 1,
+       .max_timeout = 0xFFFF
+};
 
 static int __init watchdog_init(void)
 {
@@ -285,37 +169,36 @@ static int __init watchdog_init(void)
 
        /* Check that the soft_margin value is within it's range;
           if not reset to the default */
-       if (softdog_set_heartbeat(soft_margin)) {
-               softdog_set_heartbeat(TIMER_MARGIN);
-               printk(KERN_INFO PFX
-                   "soft_margin must be 0 < soft_margin < 65536, using %d\n",
+       if (soft_margin < 1 || soft_margin > 65535) {
+               pr_info("soft_margin must be 0 < soft_margin < 65536, using %d\n",
                        TIMER_MARGIN);
+               return -EINVAL;
        }
+       softdog_dev.timeout = soft_margin;
+
+       watchdog_set_nowayout(&softdog_dev, nowayout);
 
        ret = register_reboot_notifier(&softdog_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                return ret;
        }
 
-       ret = misc_register(&softdog_miscdev);
+       ret = watchdog_register_device(&softdog_dev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&softdog_notifier);
                return ret;
        }
 
-       printk(banner, soft_noboot, soft_margin, soft_panic, nowayout);
+       pr_info("Software Watchdog Timer: 0.08 initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d (nowayout=%d)\n",
+               soft_noboot, soft_margin, soft_panic, nowayout);
 
        return 0;
 }
 
 static void __exit watchdog_exit(void)
 {
-       misc_deregister(&softdog_miscdev);
+       watchdog_unregister_device(&softdog_dev);
        unregister_reboot_notifier(&softdog_notifier);
 }
 
index 87e0527669d8c0860c091ffb3412621fae126a7f..59108e48ada35aed040136d05db41e5df80e09fb 100644 (file)
@@ -20,6 +20,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -39,7 +41,6 @@
 #define TCO_VERSION "0.01"
 #define TCO_MODULE_NAME "SP5100 TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
-#define PFX TCO_MODULE_NAME ": "
 
 /* internal variables */
 static u32 tcobase_phys;
@@ -61,8 +62,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
                 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -143,8 +144,7 @@ static int sp5100_tco_release(struct inode *inode, struct file *file)
        if (tco_expect_close == 42) {
                tco_timer_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                tco_timer_keepalive();
        }
        clear_bit(0, &timer_alive);
@@ -290,8 +290,7 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
        /* Request the IO ports used by this driver */
        pm_iobase = SP5100_IO_PM_INDEX_REG;
        if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       pm_iobase);
+               pr_err("I/O address 0x%04x already in use\n", pm_iobase);
                goto exit;
        }
 
@@ -308,15 +307,14 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
 
        if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
                                                                "SP5100 TCO")) {
-               printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
-                       val);
+               pr_err("mmio address 0x%04x already in use\n", val);
                goto unreg_region;
        }
        tcobase_phys = val;
 
        tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
        if (tcobase == 0) {
-               printk(KERN_ERR PFX "failed to get tcobase address\n");
+               pr_err("failed to get tcobase address\n");
                goto unreg_mem_region;
        }
 
@@ -375,9 +373,9 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)
                return -ENODEV;
 
        /* Check to see if last reboot was due to watchdog timeout */
-       printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
-              readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
-                     "" : "not ");
+       pr_info("Watchdog reboot %sdetected\n",
+               readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
+               "" : "not ");
 
        /* Clear out the old status */
        val = readl(SP5100_WDT_CONTROL(tcobase));
@@ -395,16 +393,14 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)
 
        ret = misc_register(&sp5100_tco_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor="
-                      "%d (err=%d)\n",
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
                       WATCHDOG_MINOR, ret);
                goto exit;
        }
 
        clear_bit(0, &timer_alive);
 
-       printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec"
-               " (nowayout=%d)\n",
+       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
                tcobase, heartbeat, nowayout);
 
        return 0;
@@ -455,8 +451,7 @@ static int __init sp5100_tco_init_module(void)
 {
        int err;
 
-       printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n",
-              TCO_VERSION);
+       pr_info("SP5100 TCO WatchDog Timer Driver v%s\n", TCO_VERSION);
 
        err = platform_driver_register(&sp5100_tco_driver);
        if (err)
@@ -480,7 +475,7 @@ static void __exit sp5100_tco_cleanup_module(void)
 {
        platform_device_unregister(sp5100_tco_platform_device);
        platform_driver_unregister(&sp5100_tco_driver);
-       printk(KERN_INFO PFX "SP5100 TCO Watchdog Module Unloaded.\n");
+       pr_info("SP5100 TCO Watchdog Module Unloaded\n");
 }
 
 module_init(sp5100_tco_init_module);
index 3ff9e47bd2188da7fcf071a6220380c82a905d2e..bbb170e50055d43e55ff783f4aa645ec45ae1d85 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
 /**
  * struct sp805_wdt: sp805 wdt device structure
- *
- * lock: spin lock protecting dev structure and io access
- * base: base address of wdt
- * clk: clock structure of wdt
- * dev: amba device structure of wdt
- * status: current status of wdt
- * load_val: load value to be set for current timeout
- * timeout: current programmed timeout
+ * @lock: spin lock protecting dev structure and io access
+ * @base: base address of wdt
+ * @clk: clock structure of wdt
+ * @adev: amba device structure of wdt
+ * @status: current status of wdt
+ * @load_val: load value to be set for current timeout
+ * @timeout: current programmed timeout
  */
 struct sp805_wdt {
        spinlock_t                      lock;
@@ -78,7 +78,7 @@ struct sp805_wdt {
 
 /* local variables */
 static struct sp805_wdt *wdt;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* This routine finds load value that will reset system in required timout */
 static void wdt_setload(unsigned int timeout)
@@ -113,10 +113,10 @@ static u32 wdt_timeleft(void)
        rate = clk_get_rate(wdt->clk);
 
        spin_lock(&wdt->lock);
-       load = readl(wdt->base + WDTVALUE);
+       load = readl_relaxed(wdt->base + WDTVALUE);
 
        /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */
-       if (!(readl(wdt->base + WDTRIS) & INT_MASK))
+       if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK))
                load += wdt->load_val + 1;
        spin_unlock(&wdt->lock);
 
@@ -128,14 +128,14 @@ static void wdt_enable(void)
 {
        spin_lock(&wdt->lock);
 
-       writel(UNLOCK, wdt->base + WDTLOCK);
-       writel(wdt->load_val, wdt->base + WDTLOAD);
-       writel(INT_MASK, wdt->base + WDTINTCLR);
-       writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
-       writel(LOCK, wdt->base + WDTLOCK);
+       writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
+       writel_relaxed(wdt->load_val, wdt->base + WDTLOAD);
+       writel_relaxed(INT_MASK, wdt->base + WDTINTCLR);
+       writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
+       writel_relaxed(LOCK, wdt->base + WDTLOCK);
 
        /* Flush posted writes. */
-       readl(wdt->base + WDTLOCK);
+       readl_relaxed(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 }
 
@@ -144,12 +144,12 @@ static void wdt_disable(void)
 {
        spin_lock(&wdt->lock);
 
-       writel(UNLOCK, wdt->base + WDTLOCK);
-       writel(0, wdt->base + WDTCONTROL);
-       writel(LOCK, wdt->base + WDTLOCK);
+       writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
+       writel_relaxed(0, wdt->base + WDTCONTROL);
+       writel_relaxed(LOCK, wdt->base + WDTLOCK);
 
        /* Flush posted writes. */
-       readl(wdt->base + WDTLOCK);
+       readl_relaxed(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 }
 
@@ -285,32 +285,33 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 {
        int ret = 0;
 
-       if (!request_mem_region(adev->res.start, resource_size(&adev->res),
-                               "sp805_wdt")) {
+       if (!devm_request_mem_region(&adev->dev, adev->res.start,
+                               resource_size(&adev->res), "sp805_wdt")) {
                dev_warn(&adev->dev, "Failed to get memory region resource\n");
                ret = -ENOENT;
                goto err;
        }
 
-       wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
+       wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL);
        if (!wdt) {
                dev_warn(&adev->dev, "Kzalloc failed\n");
                ret = -ENOMEM;
-               goto err_kzalloc;
+               goto err;
+       }
+
+       wdt->base = devm_ioremap(&adev->dev, adev->res.start,
+                       resource_size(&adev->res));
+       if (!wdt->base) {
+               ret = -ENOMEM;
+               dev_warn(&adev->dev, "ioremap fail\n");
+               goto err;
        }
 
        wdt->clk = clk_get(&adev->dev, NULL);
        if (IS_ERR(wdt->clk)) {
                dev_warn(&adev->dev, "Clock not found\n");
                ret = PTR_ERR(wdt->clk);
-               goto err_clk_get;
-       }
-
-       wdt->base = ioremap(adev->res.start, resource_size(&adev->res));
-       if (!wdt->base) {
-               ret = -ENOMEM;
-               dev_warn(&adev->dev, "ioremap fail\n");
-               goto err_ioremap;
+               goto err;
        }
 
        wdt->adev = adev;
@@ -327,14 +328,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
        return 0;
 
 err_misc_register:
-       iounmap(wdt->base);
-err_ioremap:
        clk_put(wdt->clk);
-err_clk_get:
-       kfree(wdt);
-       wdt = NULL;
-err_kzalloc:
-       release_mem_region(adev->res.start, resource_size(&adev->res));
 err:
        dev_err(&adev->dev, "Probe Failed!!!\n");
        return ret;
@@ -343,14 +337,42 @@ err:
 static int __devexit sp805_wdt_remove(struct amba_device *adev)
 {
        misc_deregister(&sp805_wdt_miscdev);
-       iounmap(wdt->base);
        clk_put(wdt->clk);
-       kfree(wdt);
-       release_mem_region(adev->res.start, resource_size(&adev->res));
 
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int sp805_wdt_suspend(struct device *dev)
+{
+       if (test_bit(WDT_BUSY, &wdt->status)) {
+               wdt_disable();
+               clk_disable(wdt->clk);
+       }
+
+       return 0;
+}
+
+static int sp805_wdt_resume(struct device *dev)
+{
+       int ret = 0;
+
+       if (test_bit(WDT_BUSY, &wdt->status)) {
+               ret = clk_enable(wdt->clk);
+               if (ret) {
+                       dev_err(dev, "clock enable fail");
+                       return ret;
+               }
+               wdt_enable();
+       }
+
+       return ret;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend,
+               sp805_wdt_resume);
+
 static struct amba_id sp805_wdt_ids[] = {
        {
                .id     = 0x00141805,
@@ -364,6 +386,7 @@ MODULE_DEVICE_TABLE(amba, sp805_wdt_ids);
 static struct amba_driver sp805_wdt_driver = {
        .drv = {
                .name   = MODULE_NAME,
+               .pm     = &sp805_wdt_dev_pm_ops,
        },
        .id_table       = sp805_wdt_ids,
        .probe          = sp805_wdt_probe,
@@ -372,7 +395,7 @@ static struct amba_driver sp805_wdt_driver = {
 
 module_amba_driver(sp805_wdt_driver);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Set to 1 to keep watchdog running after device release");
 
index e37d81178b9e7bd5326cd5dbbbfafe3f91a2d885..21d96b92bfd7b084e722028307926281dc93fa39 100644 (file)
@@ -6,6 +6,9 @@
  * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -32,7 +35,7 @@
 
 static DEFINE_SPINLOCK(stmp3xxx_wdt_io_lock);
 static unsigned long wdt_status;
-static const int nowayout = WATCHDOG_NOWAYOUT;
+static const bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = DEFAULT_HEARTBEAT;
 static unsigned long boot_status;
 
@@ -221,8 +224,7 @@ static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
                return ret;
        }
 
-       printk(KERN_INFO "stmp3xxx watchdog: initialized, heartbeat %d sec\n",
-               heartbeat);
+       pr_info("initialized, heartbeat %d sec\n", heartbeat);
 
        return ret;
 }
index 1490293dc7dad9167f61043db7187074ff0ff021..8df050d800e63e2b8467fbab6307ee8e511cb074 100644 (file)
@@ -34,8 +34,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. "
                          __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT)
                          ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 /**
index 0764c6239b98c8bb7793aca5c4b4486d79d7dac0..249f11305d263797d2863d1873f3252fd2ed8bd8 100644 (file)
@@ -42,8 +42,8 @@ struct twl4030_wdt {
        unsigned long           state;
 };
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 9e9ed7bfabcb1a51deae636635d0f33914cf201c..98e16373e6404954cf1f955a8aebbe9ecae1a5d7 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/uaccess.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <asm/txx9tmr.h>
 
+#define WD_TIMER_CCD   7               /* 1/256 */
+#define WD_TIMER_CLK   (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD))
+#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK)
 #define TIMER_MARGIN   60              /* Default is 60 seconds */
 
-static int timeout = TIMER_MARGIN;     /* in seconds */
-module_param(timeout, int, 0);
+static unsigned int timeout = TIMER_MARGIN;    /* in seconds */
+module_param(timeout, uint, 0);
 MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. "
        "(0<timeout<((2^" __MODULE_STRING(TXX9_TIMER_BITS) ")/(IMCLK/256)), "
        "default=" __MODULE_STRING(TIMER_MARGIN) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-#define WD_TIMER_CCD   7       /* 1/256 */
-#define WD_TIMER_CLK   (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD))
-#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK)
-
-static unsigned long txx9wdt_alive;
-static int expect_close;
 static struct txx9_tmr_reg __iomem *txx9wdt_reg;
 static struct clk *txx9_imclk;
 static DEFINE_SPINLOCK(txx9_lock);
 
-static void txx9wdt_ping(void)
+static int txx9wdt_ping(struct watchdog_device *wdt_dev)
 {
        spin_lock(&txx9_lock);
        __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
        spin_unlock(&txx9_lock);
+       return 0;
 }
 
-static void txx9wdt_start(void)
+static int txx9wdt_start(struct watchdog_device *wdt_dev)
 {
        spin_lock(&txx9_lock);
-       __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra);
+       __raw_writel(WD_TIMER_CLK * wdt_dev->timeout, &txx9wdt_reg->cpra);
        __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr);
        __raw_writel(0, &txx9wdt_reg->tisr);    /* clear pending interrupt */
        __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
                     &txx9wdt_reg->tcr);
        __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
        spin_unlock(&txx9_lock);
+       return 0;
 }
 
-static void txx9wdt_stop(void)
+static int txx9wdt_stop(struct watchdog_device *wdt_dev)
 {
        spin_lock(&txx9_lock);
        __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr);
        __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE,
                     &txx9wdt_reg->tcr);
        spin_unlock(&txx9_lock);
-}
-
-static int txx9wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &txx9wdt_alive))
-               return -EBUSY;
-
-       if (__raw_readl(&txx9wdt_reg->tcr) & TXx9_TMTCR_TCE) {
-               clear_bit(0, &txx9wdt_alive);
-               return -EBUSY;
-       }
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       txx9wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int txx9wdt_release(struct inode *inode, struct file *file)
-{
-       if (expect_close)
-               txx9wdt_stop();
-       else {
-               printk(KERN_CRIT "txx9wdt: "
-                      "Unexpected close, not stopping watchdog!\n");
-               txx9wdt_ping();
-       }
-       clear_bit(0, &txx9wdt_alive);
-       expect_close = 0;
        return 0;
 }
 
-static ssize_t txx9wdt_write(struct file *file, const char __user *data,
-                            size_t len, loff_t *ppos)
+static int txx9wdt_set_timeout(struct watchdog_device *wdt_dev,
+                              unsigned int new_timeout)
 {
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       expect_close = 0;
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 1;
-                       }
-               }
-               txx9wdt_ping();
-       }
-       return len;
+       wdt_dev->timeout = new_timeout;
+       txx9wdt_stop(wdt_dev);
+       txx9wdt_start(wdt_dev);
+       return 0;
 }
 
-static long txx9wdt_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_timeout;
-       static const struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "Hardware Watchdog for TXx9",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-       case WDIOC_KEEPALIVE:
-               txx9wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, p))
-                       return -EFAULT;
-               if (new_timeout < 1 || new_timeout > WD_MAX_TIMEOUT)
-                       return -EINVAL;
-               timeout = new_timeout;
-               txx9wdt_stop();
-               txx9wdt_start();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout, p);
-       default:
-               return -ENOTTY;
-       }
-}
+static const struct watchdog_info txx9wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+       .identity = "Hardware Watchdog for TXx9",
+};
 
-static const struct file_operations txx9wdt_fops = {
-       .owner          =       THIS_MODULE,
-       .llseek         =       no_llseek,
-       .write          =       txx9wdt_write,
-       .unlocked_ioctl =       txx9wdt_ioctl,
-       .open           =       txx9wdt_open,
-       .release        =       txx9wdt_release,
+static const struct watchdog_ops txx9wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = txx9wdt_start,
+       .stop = txx9wdt_stop,
+       .ping = txx9wdt_ping,
+       .set_timeout = txx9wdt_set_timeout,
 };
 
-static struct miscdevice txx9wdt_miscdev = {
-       .minor  =       WATCHDOG_MINOR,
-       .name   =       "watchdog",
-       .fops   =       &txx9wdt_fops,
+static struct watchdog_device txx9wdt = {
+       .info = &txx9wdt_info,
+       .ops = &txx9wdt_ops,
 };
 
 static int __init txx9wdt_probe(struct platform_device *dev)
@@ -199,27 +121,27 @@ static int __init txx9wdt_probe(struct platform_device *dev)
        }
 
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res)
-               goto exit_busy;
-       if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
-                                    "txx9wdt"))
-               goto exit_busy;
-       txx9wdt_reg = devm_ioremap(&dev->dev, res->start, resource_size(res));
-       if (!txx9wdt_reg)
-               goto exit_busy;
-
-       ret = misc_register(&txx9wdt_miscdev);
-       if (ret) {
+       txx9wdt_reg = devm_request_and_ioremap(&dev->dev, res);
+       if (!txx9wdt_reg) {
+               ret = -EBUSY;
                goto exit;
        }
 
-       printk(KERN_INFO "Hardware Watchdog Timer for TXx9: "
-              "timeout=%d sec (max %ld) (nowayout= %d)\n",
-              timeout, WD_MAX_TIMEOUT, nowayout);
+       if (timeout < 1 || timeout > WD_MAX_TIMEOUT)
+               timeout = TIMER_MARGIN;
+       txx9wdt.timeout = timeout;
+       txx9wdt.min_timeout = 1;
+       txx9wdt.max_timeout = WD_MAX_TIMEOUT;
+       watchdog_set_nowayout(&txx9wdt, nowayout);
+
+       ret = watchdog_register_device(&txx9wdt);
+       if (ret)
+               goto exit;
+
+       pr_info("Hardware Watchdog Timer: timeout=%d sec (max %ld) (nowayout= %d)\n",
+               timeout, WD_MAX_TIMEOUT, nowayout);
 
        return 0;
-exit_busy:
-       ret = -EBUSY;
 exit:
        if (txx9_imclk) {
                clk_disable(txx9_imclk);
@@ -230,7 +152,7 @@ exit:
 
 static int __exit txx9wdt_remove(struct platform_device *dev)
 {
-       misc_deregister(&txx9wdt_miscdev);
+       watchdog_unregister_device(&txx9wdt);
        clk_disable(txx9_imclk);
        clk_put(txx9_imclk);
        return 0;
@@ -238,7 +160,7 @@ static int __exit txx9wdt_remove(struct platform_device *dev)
 
 static void txx9wdt_shutdown(struct platform_device *dev)
 {
-       txx9wdt_stop();
+       txx9wdt_stop(&txx9wdt);
 }
 
 static struct platform_driver txx9wdt_driver = {
index 8f07dd4bd94a67385d3c44093a8a9f5c75e8f960..465e08273c972c3df5ca01bcf9a44487520cc0bc 100644 (file)
@@ -10,6 +10,9 @@
  * Caveat: PnP must be enabled in BIOS to allow full access to watchdog
  * control registers. If not, the watchdog must be configured in BIOS manually.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
@@ -55,8 +58,8 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, between 1 and 1023 "
        "(default = " __MODULE_STRING(WDT_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default = " __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -98,7 +101,7 @@ static void wdt_timer_tick(unsigned long data)
 static int wdt_ping(struct watchdog_device *wdd)
 {
        /* calculate when the next userspace timeout will be */
-       next_heartbeat = jiffies + timeout * HZ;
+       next_heartbeat = jiffies + wdd->timeout * HZ;
        return 0;
 }
 
@@ -106,7 +109,7 @@ static int wdt_start(struct watchdog_device *wdd)
 {
        unsigned int ctl = readl(wdt_mem);
 
-       writel(timeout, wdt_mem + VIA_WDT_COUNT);
+       writel(wdd->timeout, wdt_mem + VIA_WDT_COUNT);
        writel(ctl | VIA_WDT_RUNNING | VIA_WDT_TRIGGER, wdt_mem);
        wdt_ping(wdd);
        mod_timer(&timer, jiffies + WDT_HEARTBEAT);
@@ -125,7 +128,7 @@ static int wdt_set_timeout(struct watchdog_device *wdd,
                           unsigned int new_timeout)
 {
        writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
-       timeout = new_timeout;
+       wdd->timeout = new_timeout;
        return 0;
 }
 
index 576a388a11644a44129759561b906a7278c8a023..92f1326f0cfc30dd24b0d829a02548ac42e0d33b 100644 (file)
@@ -26,6 +26,8 @@
  *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
 static unsigned long wdt_is_open;
@@ -61,8 +61,8 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -119,9 +119,8 @@ static void w83627hf_init(void)
        outb_p(0xF6, WDT_EFER); /* Select CRF6 */
        t = inb_p(WDT_EFDR);      /* read CRF6 */
        if (t != 0) {
-               printk(KERN_INFO PFX
-                    "Watchdog already running. Resetting timeout to %d sec\n",
-                                                               timeout);
+               pr_info("Watchdog already running. Resetting timeout to %d sec\n",
+                       timeout);
                outb_p(timeout, WDT_EFDR);    /* Write back to CRF6 */
        }
 
@@ -290,8 +289,7 @@ static int wdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wdt_disable();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -344,18 +342,16 @@ static int __init wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising.\n");
+       pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                    "timeout value must be 1 <= timeout <= 255, using %d\n",
-                               WATCHDOG_TIMEOUT);
+               pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_io);
+               pr_err("I/O address 0x%04x already in use\n", wdt_io);
                ret = -EIO;
                goto out;
        }
@@ -364,22 +360,19 @@ static int __init wdt_init(void)
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto unreg_regions;
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX
-                       "initialized. timeout=%d sec (nowayout=%d)\n",
-                                                       timeout, nowayout);
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
 out:
        return ret;
index af08972de50684bf783342ad7c7ac554e2b8e8ea..cd9f3c1e1af44bc14cdd5b116176b9262a783a96 100644 (file)
@@ -25,6 +25,8 @@
  *     "AS-IS" and at no charge.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_NAME "w83697hf/hg WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 #define WATCHDOG_EARLY_DISABLE 1       /* Disable until userland kicks in */
 
@@ -62,8 +62,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=255 (default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -309,8 +309,7 @@ static int wdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wdt_disable();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -362,24 +361,21 @@ static struct notifier_block wdt_notifier = {
 static int w83697hf_check_wdt(void)
 {
        if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX
-                       "I/O address 0x%x already in use\n", wdt_io);
+               pr_err("I/O address 0x%x already in use\n", wdt_io);
                return -EIO;
        }
 
-       printk(KERN_DEBUG PFX
-                       "Looking for watchdog at address 0x%x\n", wdt_io);
+       pr_debug("Looking for watchdog at address 0x%x\n", wdt_io);
        w83697hf_unlock();
        if (w83697hf_get_reg(0x20) == 0x60) {
-               printk(KERN_INFO PFX
-                       "watchdog found at address 0x%x\n", wdt_io);
+               pr_info("watchdog found at address 0x%x\n", wdt_io);
                w83697hf_lock();
                return 0;
        }
        /* Reprotect in case it was a compatible device */
        w83697hf_lock();
 
-       printk(KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io);
+       pr_info("watchdog not found at address 0x%x\n", wdt_io);
        release_region(wdt_io, 2);
        return -EIO;
 }
@@ -390,7 +386,7 @@ static int __init wdt_init(void)
 {
        int ret, i, found = 0;
 
-       printk(KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
+       pr_info("WDT driver for W83697HF/HG initializing\n");
 
        if (wdt_io == 0) {
                /* we will autodetect the W83697HF/HG watchdog */
@@ -405,7 +401,7 @@ static int __init wdt_init(void)
        }
 
        if (!found) {
-               printk(KERN_ERR PFX "No W83697HF/HG could be found\n");
+               pr_err("No W83697HF/HG could be found\n");
                ret = -EIO;
                goto out;
        }
@@ -413,34 +409,30 @@ static int __init wdt_init(void)
        w83697hf_init();
        if (early_disable) {
                if (wdt_running())
-                       printk(KERN_WARNING PFX "Stopping previously enabled "
-                                       "watchdog until userland kicks in\n");
+                       pr_warn("Stopping previously enabled watchdog until userland kicks in\n");
                wdt_disable();
        }
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                    "timeout value must be 1 <= timeout <= 255, using %d\n",
-                                                       WATCHDOG_TIMEOUT);
+               pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto unreg_regions;
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
 out:
index be9c4d839e152336d6e992bc5850f31c802a9a2d..274be0bfaf244878438411fb025063352cb51f91 100644 (file)
@@ -30,6 +30,8 @@
  *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_NAME "w83697ug/uf WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
 static unsigned long wdt_is_open;
@@ -64,8 +64,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=255 (default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -91,8 +91,8 @@ static int w83697ug_select_wd_register(void)
        version = inb(WDT_EFDR);
 
        if (version == 0x68) {  /* W83697UG             */
-               printk(KERN_INFO PFX "Watchdog chip version 0x%02x = "
-                       "W83697UG/UF found at 0x%04x\n", version, wdt_io);
+               pr_info("Watchdog chip version 0x%02x = W83697UG/UF found at 0x%04x\n",
+                       version, wdt_io);
 
                outb_p(0x2b, WDT_EFER);
                c = inb_p(WDT_EFDR);    /* select WDT0 */
@@ -101,7 +101,7 @@ static int w83697ug_select_wd_register(void)
                outb_p(c, WDT_EFDR);    /* set pin118 to WDT0 */
 
        } else {
-               printk(KERN_ERR PFX "No W83697UG/UF could be found\n");
+               pr_err("No W83697UG/UF could be found\n");
                return -ENODEV;
        }
 
@@ -131,8 +131,8 @@ static int w83697ug_init(void)
        outb_p(0xF6, WDT_EFER); /* Select CRF6 */
        t = inb_p(WDT_EFDR);    /* read CRF6 */
        if (t != 0) {
-               printk(KERN_INFO PFX "Watchdog already running."
-                       " Resetting timeout to %d sec\n", timeout);
+               pr_info("Watchdog already running. Resetting timeout to %d sec\n",
+                       timeout);
                outb_p(timeout, WDT_EFDR);    /* Write back to CRF6 */
        }
        outb_p(0xF5, WDT_EFER); /* Select CRF5 */
@@ -286,8 +286,7 @@ static int wdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wdt_disable();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -340,18 +339,16 @@ static int __init wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising.\n");
+       pr_info("WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising\n");
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be 1<=timeout<=255, using %d\n",
+               pr_info("timeout value must be 1<=timeout<=255, using %d\n",
                        WATCHDOG_TIMEOUT);
        }
 
        if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_io);
+               pr_err("I/O address 0x%04x already in use\n", wdt_io);
                ret = -EIO;
                goto out;
        }
@@ -362,20 +359,18 @@ static int __init wdt_init(void)
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto unreg_regions;
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
 out:
index 24587d2060c40e16821b4470ee7602df99def4f2..7874ae06232b3648757c1529c8df5aaa10729d16 100644 (file)
@@ -42,6 +42,8 @@
  *  daemon always getting scheduled within that time frame.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #define OUR_NAME "w83877f_wdt"
-#define PFX OUR_NAME ": "
 
 #define ENABLE_W83877F_PORT 0x3F0
 #define ENABLE_W83877F 0x87
@@ -91,8 +91,8 @@ MODULE_PARM_DESC(timeout,
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -126,8 +126,7 @@ static void wdt_timer_ping(unsigned long data)
                spin_unlock(&wdt_spinlock);
 
        } else
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
 }
 
 /*
@@ -165,7 +164,7 @@ static void wdt_startup(void)
 
        wdt_change(WDT_ENABLE);
 
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 static void wdt_turnoff(void)
@@ -175,7 +174,7 @@ static void wdt_turnoff(void)
 
        wdt_change(WDT_DISABLE);
 
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
 }
 
 static void wdt_keepalive(void)
@@ -234,8 +233,7 @@ static int fop_close(struct inode *inode, struct file *file)
                wdt_turnoff();
        else {
                del_timer(&timer);
-               printk(KERN_CRIT PFX
-                 "device file closed unexpectedly. Will not stop the WDT!\n");
+               pr_crit("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &wdt_is_open);
        wdt_expect_close = 0;
@@ -357,42 +355,37 @@ static int __init w83877f_wdt_init(void)
 
        if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 3600, using %d\n",
-                                                       timeout);
+               pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
+                       timeout);
        }
 
        if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       ENABLE_W83877F_PORT);
+               pr_err("I/O address 0x%04x already in use\n",
+                      ENABLE_W83877F_PORT);
                rc = -EIO;
                goto err_out;
        }
 
        if (!request_region(WDT_PING, 1, "W8387FF WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       WDT_PING);
+               pr_err("I/O address 0x%04x already in use\n", WDT_PING);
                rc = -EIO;
                goto err_out_region1;
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region2;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
-       printk(KERN_INFO PFX
-         "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
+       pr_info("WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
        return 0;
index 6e6743d1066fb9d4aa9dcf6affa7d534ec374210..5d2c902825c2ec558f0044b3cc07b4c0a4620894 100644 (file)
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_VERSION  "1.00"
 #define WATCHDOG_NAME     "W83977F WDT"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
 
 #define IO_INDEX_PORT     0x3F0
 #define IO_DATA_PORT      (IO_INDEX_PORT+1)
@@ -59,8 +58,8 @@ MODULE_PARM_DESC(timeout,
 module_param(testmode, int, 0);
 MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -131,7 +130,7 @@ static int wdt_start(void)
 
        spin_unlock_irqrestore(&spinlock, flags);
 
-       printk(KERN_INFO PFX "activated.\n");
+       pr_info("activated\n");
 
        return 0;
 }
@@ -185,7 +184,7 @@ static int wdt_stop(void)
 
        spin_unlock_irqrestore(&spinlock, flags);
 
-       printk(KERN_INFO PFX "shutdown.\n");
+       pr_info("shutdown\n");
 
        return 0;
 }
@@ -313,8 +312,7 @@ static int wdt_release(struct inode *inode, struct file *file)
                clear_bit(0, &timer_alive);
        } else {
                wdt_keepalive();
-               printk(KERN_CRIT PFX
-                       "unexpected close, not stopping watchdog!\n");
+               pr_crit("unexpected close, not stopping watchdog!\n");
        }
        expect_close = 0;
        return 0;
@@ -471,7 +469,7 @@ static int __init w83977f_wdt_init(void)
 {
        int rc;
 
-       printk(KERN_INFO PFX DRIVER_VERSION);
+       pr_info("driver v%s\n", WATCHDOG_VERSION);
 
        /*
         * Check that the timeout value is within it's range;
@@ -479,36 +477,31 @@ static int __init w83977f_wdt_init(void)
         */
        if (wdt_set_timeout(timeout)) {
                wdt_set_timeout(DEFAULT_TIMEOUT);
-               printk(KERN_INFO PFX
-                   "timeout value must be 15 <= timeout <= 7635, using %d\n",
-                                                       DEFAULT_TIMEOUT);
+               pr_info("timeout value must be 15 <= timeout <= 7635, using %d\n",
+                       DEFAULT_TIMEOUT);
        }
 
        if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       IO_INDEX_PORT);
+               pr_err("I/O address 0x%04x already in use\n", IO_INDEX_PORT);
                rc = -EIO;
                goto err_out;
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
-       printk(KERN_INFO PFX
-               "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
-                                       timeout, nowayout, testmode);
+       pr_info("initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+               timeout, nowayout, testmode);
 
        return 0;
 
index c3c3188c34d744312cf8e1dbe3e2c30426e87248..25aba6e00a23ffc49f344709d4149d3991958bfd 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/miscdevice.h>
@@ -65,8 +67,8 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
                                __MODULE_STRING(WD_TIMO) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -203,8 +205,7 @@ static int wafwdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wafwdt_stop();
        else {
-               printk(KERN_CRIT PFX
-                   "WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
                wafwdt_ping();
        }
        clear_bit(0, &wafwdt_is_open);
@@ -256,49 +257,42 @@ static int __init wafwdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO
-         "WDT driver for Wafer 5823 single board computer initialising.\n");
+       pr_info("WDT driver for Wafer 5823 single board computer initialising\n");
 
        if (timeout < 1 || timeout > 255) {
                timeout = WD_TIMO;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 255, using %d\n",
-                                                               timeout);
+               pr_info("timeout value must be 1 <= x <= 255, using %d\n",
+                       timeout);
        }
 
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n", wdt_stop);
                        ret = -EIO;
                        goto error;
                }
        }
 
        if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                ret = -EIO;
                goto error2;
        }
 
        ret = register_reboot_notifier(&wafwdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto error3;
        }
 
        ret = misc_register(&wafwdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto error4;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
        return ret;
index cfa1a1518aadaa19c7d4e296c9ce2e5826e3e5f0..14d768bfa267d78923a467484ed1f66275471bb2 100644 (file)
@@ -77,7 +77,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
        /* We only support 1 watchdog device via the /dev/watchdog interface */
        ret = watchdog_dev_register(wdd);
        if (ret) {
-               pr_err("error registering /dev/watchdog (err=%d).\n", ret);
+               pr_err("error registering /dev/watchdog (err=%d)\n", ret);
                return ret;
        }
 
@@ -101,7 +101,7 @@ void watchdog_unregister_device(struct watchdog_device *wdd)
 
        ret = watchdog_dev_unregister(wdd);
        if (ret)
-               pr_err("error unregistering /dev/watchdog (err=%d).\n", ret);
+               pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
 }
 EXPORT_SYMBOL_GPL(watchdog_unregister_device);
 
index 1199da0f98cf2ada1a3a8868c57561f742e723df..8558da912c42fd76c5bde4ddd55528ed0be48615 100644 (file)
@@ -226,7 +226,6 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
                err = wdd->ops->set_timeout(wdd, val);
                if (err < 0)
                        return err;
-               wdd->timeout = val;
                /* If the watchdog is active then we send a keepalive ping
                 * to make sure that the watchdog keep's running (and if
                 * possible that it takes the new timeout) */
@@ -237,6 +236,11 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
                if (wdd->timeout == 0)
                        return -EOPNOTSUPP;
                return put_user(wdd->timeout, p);
+       case WDIOC_GETTIMELEFT:
+               if (!wdd->ops->get_timeleft)
+                       return -EOPNOTSUPP;
+
+               return put_user(wdd->ops->get_timeleft(wdd), p);
        default:
                return -ENOTTY;
        }
@@ -347,7 +351,7 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
 
        /* Only one device can register for /dev/watchdog */
        if (test_and_set_bit(0, &watchdog_dev_busy)) {
-               pr_err("only one watchdog can use /dev/watchdog.\n");
+               pr_err("only one watchdog can use /dev/watchdog\n");
                return -EBUSY;
        }
 
@@ -355,8 +359,8 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
 
        err = misc_register(&watchdog_miscdev);
        if (err != 0) {
-               pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
-                       watchdog->info->identity, WATCHDOG_MINOR, err);
+               pr_err("%s: cannot register miscdev on minor=%d (err=%d)\n",
+                      watchdog->info->identity, WATCHDOG_MINOR, err);
                goto out;
        }
 
@@ -383,8 +387,8 @@ int watchdog_dev_unregister(struct watchdog_device *watchdog)
 
        /* We can only unregister the watchdog device that was registered */
        if (watchdog != wdd) {
-               pr_err("%s: watchdog was not registered as /dev/watchdog.\n",
-                       watchdog->info->identity);
+               pr_err("%s: watchdog was not registered as /dev/watchdog\n",
+                      watchdog->info->identity);
                return -ENODEV;
        }
 
index 94ec22b9e66bda7db6f96ace71df36afe6f35f9f..0a77655cda60d6341f379d674b48bce17e6166c3 100644 (file)
@@ -26,6 +26,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -49,7 +51,7 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS_MISCDEV(TEMP_MINOR);
 
-static int wdrtas_nowayout = WATCHDOG_NOWAYOUT;
+static bool wdrtas_nowayout = WATCHDOG_NOWAYOUT;
 static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
 static char wdrtas_expect_close;
 
@@ -93,8 +95,8 @@ static int wdrtas_set_interval(int interval)
        result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
                           WDRTAS_SURVEILLANCE_IND, 0, interval);
        if (result < 0 && print_msg) {
-               printk(KERN_ERR "wdrtas: setting the watchdog to %i "
-                      "timeout failed: %li\n", interval, result);
+               pr_err("setting the watchdog to %i timeout failed: %li\n",
+                      interval, result);
                print_msg--;
        }
 
@@ -128,8 +130,8 @@ static int wdrtas_get_interval(int fallback_value)
        spin_unlock(&rtas_data_buf_lock);
 
        if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) {
-               printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
-                      "timeout (%li). Continuing\n", result);
+               pr_warn("could not get sp_spi watchdog timeout (%li). Continuing\n",
+                       result);
                return fallback_value;
        }
 
@@ -170,18 +172,18 @@ static void wdrtas_log_scanned_event(void)
        int i;
 
        for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
-               printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
-                      "%02x %02x %02x %02x  %02x %02x %02x %02x   "
-                      "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                      (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
-                      wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
-                      wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
-                      wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
-                      wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
-                      wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
-                      wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
-                      wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
-                      wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
+               pr_info("dumping event (line %i/%i), data = "
+                       "%02x %02x %02x %02x  %02x %02x %02x %02x   "
+                       "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
+                       wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
+                       wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
+                       wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
+                       wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
+                       wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
+                       wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
+                       wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
+                       wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
 }
 
 /**
@@ -201,8 +203,7 @@ static void wdrtas_timer_keepalive(void)
                                   (void *)__pa(wdrtas_logbuffer),
                                   WDRTAS_LOGBUFFER_LEN);
                if (result < 0)
-                       printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
-                              result);
+                       pr_err("event-scan failed: %li\n", result);
                if (result == 0)
                        wdrtas_log_scanned_event();
        } while (result == 0);
@@ -224,8 +225,7 @@ static int wdrtas_get_temperature(void)
        result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature);
 
        if (result < 0)
-               printk(KERN_WARNING "wdrtas: reading the thermal sensor "
-                      "failed: %i\n", result);
+               pr_warn("reading the thermal sensor failed: %i\n", result);
        else
                temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
 
@@ -419,8 +419,7 @@ static int wdrtas_close(struct inode *inode, struct file *file)
        if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
                wdrtas_timer_stop();
        else {
-               printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
-                      "not stopped.\n");
+               pr_warn("got unexpected close. Watchdog not stopped.\n");
                wdrtas_timer_keepalive();
        }
 
@@ -552,30 +551,24 @@ static int wdrtas_get_tokens(void)
 {
        wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
        if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_WARNING "wdrtas: couldn't get token for "
-                      "get-sensor-state. Trying to continue without "
-                      "temperature support.\n");
+               pr_warn("couldn't get token for get-sensor-state. Trying to continue without temperature support.\n");
        }
 
        wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
        if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_WARNING "wdrtas: couldn't get token for "
-                      "ibm,get-system-parameter. Trying to continue with "
-                      "a default timeout value of %i seconds.\n",
-                      WDRTAS_DEFAULT_INTERVAL);
+               pr_warn("couldn't get token for ibm,get-system-parameter. Trying to continue with a default timeout value of %i seconds.\n",
+                       WDRTAS_DEFAULT_INTERVAL);
        }
 
        wdrtas_token_set_indicator = rtas_token("set-indicator");
        if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_ERR "wdrtas: couldn't get token for "
-                      "set-indicator. Terminating watchdog code.\n");
+               pr_err("couldn't get token for set-indicator. Terminating watchdog code.\n");
                return -EIO;
        }
 
        wdrtas_token_event_scan = rtas_token("event-scan");
        if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
-                      "Terminating watchdog code.\n");
+               pr_err("couldn't get token for event-scan. Terminating watchdog code.\n");
                return -EIO;
        }
 
@@ -609,17 +602,14 @@ static int wdrtas_register_devs(void)
 
        result = misc_register(&wdrtas_miscdev);
        if (result) {
-               printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
-                      "device. Terminating watchdog code.\n");
+               pr_err("couldn't register watchdog misc device. Terminating watchdog code.\n");
                return result;
        }
 
        if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
                result = misc_register(&wdrtas_tempdev);
                if (result) {
-                       printk(KERN_WARNING "wdrtas: couldn't register "
-                              "watchdog temperature misc device. Continuing "
-                              "without temperature support.\n");
+                       pr_warn("couldn't register watchdog temperature misc device. Continuing without temperature support.\n");
                        wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
                }
        }
@@ -643,8 +633,7 @@ static int __init wdrtas_init(void)
                return -ENODEV;
 
        if (register_reboot_notifier(&wdrtas_notifier)) {
-               printk(KERN_ERR "wdrtas: could not register reboot notifier. "
-                      "Terminating watchdog code.\n");
+               pr_err("could not register reboot notifier. Terminating watchdog code.\n");
                wdrtas_unregister_devs();
                return -ENODEV;
        }
index d2ef002be96b5f6346b9c5236678a74181330d32..ee4333c01109335088dbbd1a5cd4124f4e2f922b 100644 (file)
@@ -32,6 +32,8 @@
  *             Matt Domsch     :       Added nowayout module option
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -46,7 +48,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include "wd501p.h"
 
 static unsigned long wdt_is_open;
@@ -65,8 +66,8 @@ MODULE_PARM_DESC(heartbeat,
        "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default="
                                __MODULE_STRING(WD_TIMO) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -252,11 +253,11 @@ static int wdt_get_temperature(void)
 static void wdt_decode_501(int status)
 {
        if (!(status & WDC_SR_TGOOD))
-               printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT));
+               pr_crit("Overheat alarm (%d)\n", inb_p(WDT_RT));
        if (!(status & WDC_SR_PSUOVER))
-               printk(KERN_CRIT "PSU over voltage.\n");
+               pr_crit("PSU over voltage\n");
        if (!(status & WDC_SR_PSUUNDR))
-               printk(KERN_CRIT "PSU under voltage.\n");
+               pr_crit("PSU under voltage\n");
 }
 
 /**
@@ -280,25 +281,25 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
        spin_lock(&wdt_lock);
        status = inb_p(WDT_SR);
 
-       printk(KERN_CRIT "WDT status %d\n", status);
+       pr_crit("WDT status %d\n", status);
 
        if (type == 501) {
                wdt_decode_501(status);
                if (tachometer) {
                        if (!(status & WDC_SR_FANGOOD))
-                               printk(KERN_CRIT "Possible fan fault.\n");
+                               pr_crit("Possible fan fault\n");
                }
        }
        if (!(status & WDC_SR_WCCR)) {
 #ifdef SOFTWARE_REBOOT
 #ifdef ONLY_TESTING
-               printk(KERN_CRIT "Would Reboot.\n");
+               pr_crit("Would Reboot\n");
 #else
-               printk(KERN_CRIT "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart();
 #endif
 #else
-               printk(KERN_CRIT "Reset in 5ms.\n");
+               pr_crit("Reset in 5ms\n");
 #endif
        }
        spin_unlock(&wdt_lock);
@@ -441,8 +442,7 @@ static int wdt_release(struct inode *inode, struct file *file)
                wdt_stop();
                clear_bit(0, &wdt_is_open);
        } else {
-               printk(KERN_CRIT
-                "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -593,7 +593,7 @@ static int __init wdt_init(void)
        int ret;
 
        if (type != 500 && type != 501) {
-               printk(KERN_ERR "wdt: unknown card type '%d'.\n", type);
+               pr_err("unknown card type '%d'\n", type);
                return -ENODEV;
        }
 
@@ -601,53 +601,49 @@ static int __init wdt_init(void)
           if not reset to the default */
        if (wdt_set_heartbeat(heartbeat)) {
                wdt_set_heartbeat(WD_TIMO);
-               printk(KERN_INFO "wdt: heartbeat value must be "
-                       "0 < heartbeat < 65536, using %d\n", WD_TIMO);
+               pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
+                       WD_TIMO);
        }
 
        if (!request_region(io, 8, "wdt501p")) {
-               printk(KERN_ERR
-                       "wdt: I/O address 0x%04x already in use\n", io);
+               pr_err("I/O address 0x%04x already in use\n", io);
                ret = -EBUSY;
                goto out;
        }
 
        ret = request_irq(irq, wdt_interrupt, 0, "wdt501p", NULL);
        if (ret) {
-               printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
+               pr_err("IRQ %d is not free\n", irq);
                goto outreg;
        }
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret) {
-               printk(KERN_ERR
-                     "wdt: cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto outirq;
        }
 
        if (type == 501) {
                ret = misc_register(&temp_miscdev);
                if (ret) {
-                       printk(KERN_ERR "wdt: cannot register miscdev "
-                               "on minor=%d (err=%d)\n", TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto outrbt;
                }
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR
-                       "wdt: cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto outmisc;
        }
 
-       printk(KERN_INFO "WDT500/501-P driver 0.10 "
-               "at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
                io, irq, heartbeat, nowayout);
        if (type == 501)
-               printk(KERN_INFO "wdt: Fan Tachometer is %s\n",
-                               (tachometer ? "Enabled" : "Disabled"));
+               pr_info("Fan Tachometer is %s\n",
+                       tachometer ? "Enabled" : "Disabled");
        return 0;
 
 outmisc:
index f55135662d78f9472ae9ebe38ef634c956225578..5eec740538824b4e529c725f8e82606b54364240 100644 (file)
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -32,6 +34,7 @@
 #include <mach/hardware.h>
 
 #include <asm/mach-types.h>
+#include <asm/system_info.h>
 #include <asm/hardware/dec21285.h>
 
 /*
@@ -49,7 +52,7 @@ static unsigned long timer_alive;
  */
 static void watchdog_fire(int irq, void *dev_id)
 {
-       printk(KERN_CRIT "Watchdog: Would Reboot.\n");
+       pr_crit("Would Reboot\n");
        *CSR_TIMER4_CNTL = 0;
        *CSR_TIMER4_CLR = 0;
 }
@@ -205,13 +208,11 @@ static int __init footbridge_watchdog_init(void)
        if (retval < 0)
                return retval;
 
-       printk(KERN_INFO
-               "Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
-                                                               soft_margin);
+       pr_info("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
+               soft_margin);
 
        if (machine_is_cats())
-               printk(KERN_WARNING
-                 "Warning: Watchdog reset may not work on this machine.\n");
+               pr_warn("Warning: Watchdog reset may not work on this machine\n");
        return 0;
 }
 
index a2f01c9f5c341af0e27079185fb0094adca3a539..65a402344933952176170de888311d72fe0bd157 100644 (file)
@@ -23,6 +23,8 @@
  *                                 Netwinders only
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #define WATCHDOG_VERSION  "0.04"
 #define WATCHDOG_NAME     "Wdt977"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
 
 #define IO_INDEX_PORT  0x370           /* on some systems it can be 0x3F0 */
 #define IO_DATA_PORT   (IO_INDEX_PORT + 1)
@@ -68,8 +67,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (60..15300, default="
 module_param(testmode, int, 0);
 MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -119,7 +118,7 @@ static int wdt977_start(void)
        outb_p(LOCK_DATA, IO_INDEX_PORT);
 
        spin_unlock_irqrestore(&spinlock, flags);
-       printk(KERN_INFO PFX "activated.\n");
+       pr_info("activated\n");
 
        return 0;
 }
@@ -164,7 +163,7 @@ static int wdt977_stop(void)
        outb_p(LOCK_DATA, IO_INDEX_PORT);
 
        spin_unlock_irqrestore(&spinlock, flags);
-       printk(KERN_INFO PFX "shutdown.\n");
+       pr_info("shutdown\n");
 
        return 0;
 }
@@ -288,8 +287,7 @@ static int wdt977_release(struct inode *inode, struct file *file)
                clear_bit(0, &timer_alive);
        } else {
                wdt977_keepalive();
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
        }
        expect_close = 0;
        return 0;
@@ -446,15 +444,14 @@ static int __init wd977_init(void)
 {
        int rc;
 
-       printk(KERN_INFO PFX DRIVER_VERSION);
+       pr_info("driver v%s\n", WATCHDOG_VERSION);
 
        /* Check that the timeout value is within its range;
           if not reset to the default */
        if (wdt977_set_timeout(timeout)) {
                wdt977_set_timeout(DEFAULT_TIMEOUT);
-               printk(KERN_INFO PFX
-                     "timeout value must be 60 < timeout < 15300, using %d\n",
-                                                       DEFAULT_TIMEOUT);
+               pr_info("timeout value must be 60 < timeout < 15300, using %d\n",
+                       DEFAULT_TIMEOUT);
        }
 
        /* on Netwinder the IOports are already reserved by
@@ -462,9 +459,8 @@ static int __init wd977_init(void)
         */
        if (!machine_is_netwinder()) {
                if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               IO_INDEX_PORT);
+                       pr_err("I/O address 0x%04x already in use\n",
+                              IO_INDEX_PORT);
                        rc = -EIO;
                        goto err_out;
                }
@@ -472,22 +468,19 @@ static int __init wd977_init(void)
 
        rc = register_reboot_notifier(&wdt977_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt977_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               wdt977_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt977_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
-       printk(KERN_INFO PFX
-               "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
-                                               timeout, nowayout, testmode);
+       pr_info("initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
+               timeout, nowayout, testmode);
 
        return 0;
 
index e0fc3baa91972f03967e5e2843350dab011c76d8..1c888c7d4cce4178fdd795657766761f074d9c75 100644 (file)
@@ -37,6 +37,8 @@
  *             Matt Domsch     :       nowayout module option
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WDT_IS_PCI
 #include "wd501p.h"
 
-#define PFX "wdt_pci: "
-
 /* We can only use 1 card due to the /dev/watchdog restriction */
 static int dev_count;
 
@@ -80,8 +79,8 @@ MODULE_PARM_DESC(heartbeat,
                "Watchdog heartbeat in seconds. (0<heartbeat<65536, default="
                                __MODULE_STRING(WD_TIMO) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -312,33 +311,32 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
        status = inb(WDT_SR);
        udelay(8);
 
-       printk(KERN_CRIT PFX "status %d\n", status);
+       pr_crit("status %d\n", status);
 
        if (type == 501) {
                if (!(status & WDC_SR_TGOOD)) {
-                       printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",
-                                                               inb(WDT_RT));
+                       pr_crit("Overheat alarm (%d)\n", inb(WDT_RT));
                        udelay(8);
                }
                if (!(status & WDC_SR_PSUOVER))
-                       printk(KERN_CRIT PFX "PSU over voltage.\n");
+                       pr_crit("PSU over voltage\n");
                if (!(status & WDC_SR_PSUUNDR))
-                       printk(KERN_CRIT PFX "PSU under voltage.\n");
+                       pr_crit("PSU under voltage\n");
                if (tachometer) {
                        if (!(status & WDC_SR_FANGOOD))
-                               printk(KERN_CRIT PFX "Possible fan fault.\n");
+                               pr_crit("Possible fan fault\n");
                }
        }
        if (!(status & WDC_SR_WCCR)) {
 #ifdef SOFTWARE_REBOOT
 #ifdef ONLY_TESTING
-               printk(KERN_CRIT PFX "Would Reboot.\n");
+               pr_crit("Would Reboot\n");
 #else
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart(NULL);
 #endif
 #else
-               printk(KERN_CRIT PFX "Reset in 5ms.\n");
+               pr_crit("Reset in 5ms\n");
 #endif
        }
        spin_unlock(&wdtpci_lock);
@@ -484,7 +482,7 @@ static int wdtpci_release(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                wdtpci_stop();
        } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
+               pr_crit("Unexpected close, not stopping timer!\n");
                wdtpci_ping();
        }
        expect_close = 0;
@@ -614,29 +612,29 @@ static int __devinit wdtpci_init_one(struct pci_dev *dev,
 
        dev_count++;
        if (dev_count > 1) {
-               printk(KERN_ERR PFX "This driver only supports one device\n");
+               pr_err("This driver only supports one device\n");
                return -ENODEV;
        }
 
        if (type != 500 && type != 501) {
-               printk(KERN_ERR PFX "unknown card type '%d'.\n", type);
+               pr_err("unknown card type '%d'\n", type);
                return -ENODEV;
        }
 
        if (pci_enable_device(dev)) {
-               printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
+               pr_err("Not possible to enable PCI Device\n");
                return -ENODEV;
        }
 
        if (pci_resource_start(dev, 2) == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               pr_err("No I/O-Address for card detected\n");
                ret = -ENODEV;
                goto out_pci;
        }
 
        if (pci_request_region(dev, 2, "wdt_pci")) {
-               printk(KERN_ERR PFX "I/O address 0x%llx already in use\n",
-                       (unsigned long long)pci_resource_start(dev, 2));
+               pr_err("I/O address 0x%llx already in use\n",
+                      (unsigned long long)pci_resource_start(dev, 2));
                goto out_pci;
        }
 
@@ -645,53 +643,48 @@ static int __devinit wdtpci_init_one(struct pci_dev *dev,
 
        if (request_irq(irq, wdtpci_interrupt, IRQF_SHARED,
                         "wdt_pci", &wdtpci_miscdev)) {
-               printk(KERN_ERR PFX "IRQ %d is not free\n", irq);
+               pr_err("IRQ %d is not free\n", irq);
                goto out_reg;
        }
 
-       printk(KERN_INFO
-        "PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
-                                       (unsigned long long)io, irq);
+       pr_info("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
+               (unsigned long long)io, irq);
 
        /* Check that the heartbeat value is within its range;
           if not reset to the default */
        if (wdtpci_set_heartbeat(heartbeat)) {
                wdtpci_set_heartbeat(WD_TIMO);
-               printk(KERN_INFO PFX
-                 "heartbeat value must be 0 < heartbeat < 65536, using %d\n",
-                                                               WD_TIMO);
+               pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
+                       WD_TIMO);
        }
 
        ret = register_reboot_notifier(&wdtpci_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto out_irq;
        }
 
        if (type == 501) {
                ret = misc_register(&temp_miscdev);
                if (ret) {
-                       printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto out_rbt;
                }
        }
 
        ret = misc_register(&wdtpci_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto out_misc;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
        if (type == 501)
-               printk(KERN_INFO "wdt: Fan Tachometer is %s\n",
-                               (tachometer ? "Enabled" : "Disabled"));
+               pr_info("Fan Tachometer is %s\n",
+                       tachometer ? "Enabled" : "Disabled");
 
        ret = 0;
 out:
index 263c883f0806933c80212f00b8e3792c3ed73db6..b1815c5ed7a72ac7c24e90e8dc62649f8a32bd0b 100644 (file)
@@ -22,8 +22,8 @@
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/watchdog.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -163,6 +163,8 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
                        ret);
        }
 
+       wdt_dev->timeout = timeout;
+
        return ret;
 }
 
index 5d7113c7e501d1b5b00f8f991bbe475a6504dd88..3c76693447fd5483ba01934e619afe74320f1e86 100644 (file)
@@ -8,63 +8,65 @@
  * as published by the Free Software Foundation
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/uaccess.h>
 #include <linux/mfd/wm8350/core.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static unsigned long wm8350_wdt_users;
-static struct miscdevice wm8350_wdt_miscdev;
-static int wm8350_wdt_expect_close;
 static DEFINE_MUTEX(wdt_mutex);
 
 static struct {
-       int time;  /* Seconds */
-       u16 val;   /* To be set in WM8350_SYSTEM_CONTROL_2 */
+       unsigned int time;  /* Seconds */
+       u16 val;            /* To be set in WM8350_SYSTEM_CONTROL_2 */
 } wm8350_wdt_cfgs[] = {
        { 1, 0x02 },
        { 2, 0x04 },
        { 4, 0x05 },
 };
 
-static struct wm8350 *get_wm8350(void)
-{
-       return dev_get_drvdata(wm8350_wdt_miscdev.parent);
-}
-
-static int wm8350_wdt_set_timeout(struct wm8350 *wm8350, u16 value)
+static int wm8350_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                 unsigned int timeout)
 {
-       int ret;
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
+       int ret, i;
        u16 reg;
 
+       for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
+               if (wm8350_wdt_cfgs[i].time == timeout)
+                       break;
+       if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
+               return -EINVAL;
+
        mutex_lock(&wdt_mutex);
        wm8350_reg_unlock(wm8350);
 
        reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
        reg &= ~WM8350_WDOG_TO_MASK;
-       reg |= value;
+       reg |= wm8350_wdt_cfgs[i].val;
        ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
 
        wm8350_reg_lock(wm8350);
        mutex_unlock(&wdt_mutex);
 
+       wdt_dev->timeout = timeout;
        return ret;
 }
 
-static int wm8350_wdt_start(struct wm8350 *wm8350)
+static int wm8350_wdt_start(struct watchdog_device *wdt_dev)
 {
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
        int ret;
        u16 reg;
 
@@ -82,8 +84,9 @@ static int wm8350_wdt_start(struct wm8350 *wm8350)
        return ret;
 }
 
-static int wm8350_wdt_stop(struct wm8350 *wm8350)
+static int wm8350_wdt_stop(struct watchdog_device *wdt_dev)
 {
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
        int ret;
        u16 reg;
 
@@ -100,8 +103,9 @@ static int wm8350_wdt_stop(struct wm8350 *wm8350)
        return ret;
 }
 
-static int wm8350_wdt_kick(struct wm8350 *wm8350)
+static int wm8350_wdt_ping(struct watchdog_device *wdt_dev)
 {
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
        int ret;
        u16 reg;
 
@@ -115,168 +119,25 @@ static int wm8350_wdt_kick(struct wm8350 *wm8350)
        return ret;
 }
 
-static int wm8350_wdt_open(struct inode *inode, struct file *file)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-       int ret;
-
-       if (!wm8350)
-               return -ENODEV;
-
-       if (test_and_set_bit(0, &wm8350_wdt_users))
-               return -EBUSY;
-
-       ret = wm8350_wdt_start(wm8350);
-       if (ret != 0)
-               return ret;
-
-       return nonseekable_open(inode, file);
-}
-
-static int wm8350_wdt_release(struct inode *inode, struct file *file)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-
-       if (wm8350_wdt_expect_close)
-               wm8350_wdt_stop(wm8350);
-       else {
-               dev_warn(wm8350->dev, "Watchdog device closed uncleanly\n");
-               wm8350_wdt_kick(wm8350);
-       }
-
-       clear_bit(0, &wm8350_wdt_users);
-
-       return 0;
-}
-
-static ssize_t wm8350_wdt_write(struct file *file,
-                               const char __user *data, size_t count,
-                               loff_t *ppos)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-       size_t i;
-
-       if (count) {
-               wm8350_wdt_kick(wm8350);
-
-               if (!nowayout) {
-                       /* In case it was set long ago */
-                       wm8350_wdt_expect_close = 0;
-
-                       /* scan to see whether or not we got the magic
-                          character */
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       wm8350_wdt_expect_close = 42;
-                       }
-               }
-       }
-       return count;
-}
-
-static const struct watchdog_info ident = {
+static const struct watchdog_info wm8350_wdt_info = {
        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "WM8350 Watchdog",
 };
 
-static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-       int ret = -ENOTTY, time, i;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       u16 reg;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, p);
-               break;
-
-       case WDIOC_SETOPTIONS:
-       {
-               int options;
-
-               if (get_user(options, p))
-                       return -EFAULT;
-
-               ret = -EINVAL;
-
-               /* Setting both simultaneously means at least one must fail */
-               if (options == WDIOS_DISABLECARD)
-                       ret = wm8350_wdt_stop(wm8350);
-
-               if (options == WDIOS_ENABLECARD)
-                       ret = wm8350_wdt_start(wm8350);
-               break;
-       }
-
-       case WDIOC_KEEPALIVE:
-               ret = wm8350_wdt_kick(wm8350);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, p);
-               if (ret)
-                       break;
-
-               if (time == 0) {
-                       if (nowayout)
-                               ret = -EINVAL;
-                       else
-                               wm8350_wdt_stop(wm8350);
-                       break;
-               }
-
-               for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
-                       if (wm8350_wdt_cfgs[i].time == time)
-                               break;
-               if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
-                       ret = -EINVAL;
-               else
-                       ret = wm8350_wdt_set_timeout(wm8350,
-                                                    wm8350_wdt_cfgs[i].val);
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
-               reg &= WM8350_WDOG_TO_MASK;
-               for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
-                       if (wm8350_wdt_cfgs[i].val == reg)
-                               break;
-               if (i == ARRAY_SIZE(wm8350_wdt_cfgs)) {
-                       dev_warn(wm8350->dev,
-                                "Unknown watchdog configuration: %x\n", reg);
-                       ret = -EINVAL;
-               } else
-                       ret = put_user(wm8350_wdt_cfgs[i].time, p);
-
-       }
-
-       return ret;
-}
-
-static const struct file_operations wm8350_wdt_fops = {
+static const struct watchdog_ops wm8350_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = wm8350_wdt_write,
-       .unlocked_ioctl = wm8350_wdt_ioctl,
-       .open = wm8350_wdt_open,
-       .release = wm8350_wdt_release,
+       .start = wm8350_wdt_start,
+       .stop = wm8350_wdt_stop,
+       .ping = wm8350_wdt_ping,
+       .set_timeout = wm8350_wdt_set_timeout,
 };
 
-static struct miscdevice wm8350_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &wm8350_wdt_fops,
+static struct watchdog_device wm8350_wdt = {
+       .info = &wm8350_wdt_info,
+       .ops = &wm8350_wdt_ops,
+       .timeout = 4,
+       .min_timeout = 1,
+       .max_timeout = 4,
 };
 
 static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
@@ -288,18 +149,18 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       /* Default to 4s timeout */
-       wm8350_wdt_set_timeout(wm8350, 0x05);
+       watchdog_set_nowayout(&wm8350_wdt, nowayout);
+       watchdog_set_drvdata(&wm8350_wdt, wm8350);
 
-       wm8350_wdt_miscdev.parent = &pdev->dev;
+       /* Default to 4s timeout */
+       wm8350_wdt_set_timeout(&wm8350_wdt, 4);
 
-       return misc_register(&wm8350_wdt_miscdev);
+       return watchdog_register_device(&wm8350_wdt);
 }
 
 static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
 {
-       misc_deregister(&wm8350_wdt_miscdev);
-
+       watchdog_unregister_device(&wm8350_wdt);
        return 0;
 }
 
index 49bd9d3955624fb367e3558ce71fa68e8b8b7596..e4a25b51165c0f5933858e5fe0068a5a7da106b7 100644 (file)
@@ -9,9 +9,10 @@
  *     2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME       "wdt"
 #define DRV_VERSION    "0.01"
-#define PFX            DRV_NAME ": "
 
 #include <linux/bug.h>
 #include <linux/errno.h>
@@ -131,16 +132,17 @@ static int xen_wdt_open(struct inode *inode, struct file *file)
 
 static int xen_wdt_release(struct inode *inode, struct file *file)
 {
+       int err = 0;
+
        if (expect_release)
-               xen_wdt_stop();
+               err = xen_wdt_stop();
        else {
-               printk(KERN_CRIT PFX
-                      "unexpected close, not stopping watchdog!\n");
+               pr_crit("unexpected close, not stopping watchdog!\n");
                xen_wdt_kick();
        }
-       is_active = false;
+       is_active = err;
        expect_release = false;
-       return 0;
+       return err;
 }
 
 static ssize_t xen_wdt_write(struct file *file, const char __user *data,
@@ -251,30 +253,27 @@ static int __devinit xen_wdt_probe(struct platform_device *dev)
        case -EINVAL:
                if (!timeout) {
                        timeout = WATCHDOG_TIMEOUT;
-                       printk(KERN_INFO PFX
-                              "timeout value invalid, using %d\n", timeout);
+                       pr_info("timeout value invalid, using %d\n", timeout);
                }
 
                ret = misc_register(&xen_wdt_miscdev);
                if (ret) {
-                       printk(KERN_ERR PFX
-                              "cannot register miscdev on minor=%d (%d)\n",
+                       pr_err("cannot register miscdev on minor=%d (%d)\n",
                               WATCHDOG_MINOR, ret);
                        break;
                }
 
-               printk(KERN_INFO PFX
-                      "initialized (timeout=%ds, nowayout=%d)\n",
-                      timeout, nowayout);
+               pr_info("initialized (timeout=%ds, nowayout=%d)\n",
+                       timeout, nowayout);
                break;
 
        case -ENOSYS:
-               printk(KERN_INFO PFX "not supported\n");
+               pr_info("not supported\n");
                ret = -ENODEV;
                break;
 
        default:
-               printk(KERN_INFO PFX "bogus return value %d\n", ret);
+               pr_info("bogus return value %d\n", ret);
                break;
        }
 
@@ -299,11 +298,18 @@ static void xen_wdt_shutdown(struct platform_device *dev)
 
 static int xen_wdt_suspend(struct platform_device *dev, pm_message_t state)
 {
-       return xen_wdt_stop();
+       typeof(wdt.id) id = wdt.id;
+       int rc = xen_wdt_stop();
+
+       wdt.id = id;
+       return rc;
 }
 
 static int xen_wdt_resume(struct platform_device *dev)
 {
+       if (!wdt.id)
+               return 0;
+       wdt.id = 0;
        return xen_wdt_start();
 }
 
@@ -326,7 +332,7 @@ static int __init xen_wdt_init_module(void)
        if (!xen_domain())
                return -ENODEV;
 
-       printk(KERN_INFO PFX "Xen WatchDog Timer Driver v%s\n", DRV_VERSION);
+       pr_info("Xen WatchDog Timer Driver v%s\n", DRV_VERSION);
 
        err = platform_driver_register(&xen_wdt_driver);
        if (err)
@@ -346,7 +352,7 @@ static void __exit xen_wdt_cleanup_module(void)
 {
        platform_device_unregister(platform_device);
        platform_driver_unregister(&xen_wdt_driver);
-       printk(KERN_INFO PFX "module unloaded\n");
+       pr_info("module unloaded\n");
 }
 
 module_init(xen_wdt_init_module);
index 85f1fcdb30e75b4ad2da3d2dd8c1286664b6a3dd..9dacb858670107bab207d4378e77d79dd3f25605 100644 (file)
@@ -230,7 +230,7 @@ static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
        fdt = files_fdtable(files);
        BUG_ON(fdt->fd[fd] != NULL);
        rcu_assign_pointer(fdt->fd[fd], file);
-       FD_SET(fd, fdt->close_on_exec);
+       __set_close_on_exec(fd, fdt);
        spin_unlock(&files->file_lock);
 }
 
index 4d5e6d26578c6da8125891e06e61d8839d460649..2eb12f13593db771987c9c4e7cd30c16515fcf11 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/coredump.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/a.out-core.h>
index 504b6eee50a9ca47fc4aa3a4e9f691eb3095ad8c..48ffb3dc610a7c9d6ea4428dd441666b4605b2c4 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
+#include <asm/exec.h>
 
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
@@ -1414,6 +1415,22 @@ static void do_thread_regset_writeback(struct task_struct *task,
                regset->writeback(task, regset, 1);
 }
 
+#ifndef PR_REG_SIZE
+#define PR_REG_SIZE(S) sizeof(S)
+#endif
+
+#ifndef PRSTATUS_SIZE
+#define PRSTATUS_SIZE(S) sizeof(S)
+#endif
+
+#ifndef PR_REG_PTR
+#define PR_REG_PTR(S) (&((S)->pr_reg))
+#endif
+
+#ifndef SET_PR_FPVALID
+#define SET_PR_FPVALID(S, V) ((S)->pr_fpvalid = (V))
+#endif
+
 static int fill_thread_core_info(struct elf_thread_core_info *t,
                                 const struct user_regset_view *view,
                                 long signr, size_t *total)
@@ -1428,11 +1445,11 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
         */
        fill_prstatus(&t->prstatus, t->task, signr);
        (void) view->regsets[0].get(t->task, &view->regsets[0],
-                                   0, sizeof(t->prstatus.pr_reg),
-                                   &t->prstatus.pr_reg, NULL);
+                                   0, PR_REG_SIZE(t->prstatus.pr_reg),
+                                   PR_REG_PTR(&t->prstatus), NULL);
 
        fill_note(&t->notes[0], "CORE", NT_PRSTATUS,
-                 sizeof(t->prstatus), &t->prstatus);
+                 PRSTATUS_SIZE(t->prstatus), &t->prstatus);
        *total += notesize(&t->notes[0]);
 
        do_thread_regset_writeback(t->task, &view->regsets[0]);
@@ -1462,7 +1479,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
                                                  regset->core_note_type,
                                                  size, data);
                                else {
-                                       t->prstatus.pr_fpvalid = 1;
+                                       SET_PR_FPVALID(&t->prstatus, 1);
                                        fill_note(&t->notes[i], "CORE",
                                                  NT_PRFPREG, size, data);
                                }
index c64bf5ee2df480e55c5fe38423b7c1ec88d5a46b..9bd5612a8224fc5c6374d4dcc27ff99a58ee76e5 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/pgalloc.h>
+#include <asm/exec.h>
 
 typedef char *elf_caddr_t;
 
index 5979027451b32190f281809519fdd77b76d069a9..024d20ee3ca3a617e377045fa7cf6d0706a4ed43 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/syscalls.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
index 70e2017edd70e68c9958d49f1692f3401013df92..36d66653b93191c9c13c21e74dea6f511a6ac9ab 100644 (file)
@@ -1384,10 +1384,23 @@ static void invalidate_bh_lru(void *arg)
        }
        put_cpu_var(bh_lrus);
 }
+
+static bool has_bh_in_lru(int cpu, void *dummy)
+{
+       struct bh_lru *b = per_cpu_ptr(&bh_lrus, cpu);
+       int i;
        
+       for (i = 0; i < BH_LRU_SIZE; i++) {
+               if (b->bhs[i])
+                       return 1;
+       }
+
+       return 0;
+}
+
 void invalidate_bh_lrus(void)
 {
-       on_each_cpu(invalidate_bh_lru, NULL, 1);
+       on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL);
 }
 EXPORT_SYMBOL_GPL(invalidate_bh_lrus);
 
index 05156c17b551de2f8a02a043018cc66b49b6ce41..2870597b5c9d37e416c03d2e894c2556713b3339 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/vfs.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include <linux/fs.h>
index 8f616e0e252c3b9ba66c9af8a1b6c8e27e4ccd7d..761d5b31b18d0b27ce83d6d7ed7a815d3e63b75d 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/poll.h>
 #include <asm/uaccess.h>
 
index 9727e0c525793354cee16b4ccb3df71598ddd843..0c68fd31fbf2bf3261a1ba1ce9c0e8a3148c4baa 100644 (file)
@@ -14,7 +14,6 @@
  * improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
  */
 
-#include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/types.h>
index 14483a715bbb304e988a10afb41b7decc3cd63ad..f2944ace7a7b4a06a29880ed8c55cdd2cccb1ada 100644 (file)
@@ -1170,10 +1170,9 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
 }
 
 asmlinkage ssize_t
-compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
-                 unsigned long vlen, u32 pos_low, u32 pos_high)
+compat_sys_preadv64(unsigned long fd, const struct compat_iovec __user *vec,
+                   unsigned long vlen, loff_t pos)
 {
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
        struct file *file;
        int fput_needed;
        ssize_t ret;
@@ -1190,6 +1189,14 @@ compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
        return ret;
 }
 
+asmlinkage ssize_t
+compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec,
+                 unsigned long vlen, u32 pos_low, u32 pos_high)
+{
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       return compat_sys_preadv64(fd, vec, vlen, pos);
+}
+
 static size_t compat_writev(struct file *file,
                            const struct compat_iovec __user *vec,
                            unsigned long vlen, loff_t *pos)
@@ -1229,10 +1236,9 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
 }
 
 asmlinkage ssize_t
-compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
-                  unsigned long vlen, u32 pos_low, u32 pos_high)
+compat_sys_pwritev64(unsigned long fd, const struct compat_iovec __user *vec,
+                    unsigned long vlen, loff_t pos)
 {
-       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
        struct file *file;
        int fput_needed;
        ssize_t ret;
@@ -1249,6 +1255,14 @@ compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
        return ret;
 }
 
+asmlinkage ssize_t
+compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec,
+                  unsigned long vlen, u32 pos_low, u32 pos_high)
+{
+       loff_t pos = ((loff_t)pos_high << 32) | pos_low;
+       return compat_sys_pwritev64(fd, vec, vlen, pos);
+}
+
 asmlinkage long
 compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
                    unsigned int nr_segs, unsigned int flags)
index 629e9ed99d0f6101949741f640b2c124e8dd71fe..739b0985b398ea2d837af83e26fa305a6cdfdc30 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/mutex.h>
 #include <linux/anon_inodes.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/mman.h>
 #include <linux/atomic.h>
index 23559c227d9cb4f9480855590df611999e852dd4..9a1d9f0a60abf77a55df5bef051047a23ef853d0 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -59,6 +59,7 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
+#include <asm/exec.h>
 
 #include <trace/events/task.h>
 #include "internal.h"
@@ -1027,10 +1028,10 @@ static void flush_old_files(struct files_struct * files)
                fdt = files_fdtable(files);
                if (i >= fdt->max_fds)
                        break;
-               set = fdt->close_on_exec->fds_bits[j];
+               set = fdt->close_on_exec[j];
                if (!set)
                        continue;
-               fdt->close_on_exec->fds_bits[j] = 0;
+               fdt->close_on_exec[j] = 0;
                spin_unlock(&files->file_lock);
                for ( ; set ; i++,set >>= 1) {
                        if (set & 1) {
@@ -2066,8 +2067,8 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
        fd_install(0, rp);
        spin_lock(&cf->file_lock);
        fdt = files_fdtable(cf);
-       FD_SET(0, fdt->open_fds);
-       FD_CLR(0, fdt->close_on_exec);
+       __set_open_fd(0, fdt);
+       __clear_close_on_exec(0, fdt);
        spin_unlock(&cf->file_lock);
 
        /* and disallow core files too */
index 7f2b590a36b761182c9d4fa56b16f11ab7171ac9..735ca06430ac9df3aadb6d470f4a16a3ea0e5f89 100644 (file)
@@ -389,7 +389,7 @@ static int exofs_sync_fs(struct super_block *sb, int wait)
        ios->length = offsetof(struct exofs_fscb, s_dev_table_oid);
        memset(fscb, 0, ios->length);
        fscb->s_nextid = cpu_to_le64(sbi->s_nextid);
-       fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles);
+       fscb->s_numfiles = cpu_to_le64(sbi->s_numfiles);
        fscb->s_magic = cpu_to_le16(sb->s_magic);
        fscb->s_newfs = 0;
        fscb->s_version = EXOFS_FSCB_VER;
@@ -529,7 +529,8 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
                             struct osd_dev_info *odi)
 {
        odi->systemid_len = le32_to_cpu(dt_dev->systemid_len);
-       memcpy(odi->systemid, dt_dev->systemid, odi->systemid_len);
+       if (likely(odi->systemid_len))
+               memcpy(odi->systemid, dt_dev->systemid, OSD_SYSTEMID_LEN);
 
        odi->osdname_len = le32_to_cpu(dt_dev->osdname_len);
        odi->osdname = dt_dev->osdname;
@@ -565,7 +566,7 @@ int __alloc_dev_table(struct exofs_sb_info *sbi, unsigned numdevs,
 
        aoded = kzalloc(sizeof(*aoded), GFP_KERNEL);
        if (unlikely(!aoded)) {
-               EXOFS_ERR("ERROR: faild allocating Device array[%d]\n",
+               EXOFS_ERR("ERROR: failed allocating Device array[%d]\n",
                          numdevs);
                return -ENOMEM;
        }
index ad56866d729a506fce577e69ef8ca2b8852d494d..b86786202643bdd8044ee85fb72a0a21bc2c9bef 100644 (file)
@@ -32,24 +32,8 @@ static unsigned char ext4_filetype_table[] = {
        DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
 };
 
-static int ext4_readdir(struct file *, void *, filldir_t);
 static int ext4_dx_readdir(struct file *filp,
                           void *dirent, filldir_t filldir);
-static int ext4_release_dir(struct inode *inode,
-                               struct file *filp);
-
-const struct file_operations ext4_dir_operations = {
-       .llseek         = ext4_llseek,
-       .read           = generic_read_dir,
-       .readdir        = ext4_readdir,         /* we take BKL. needed?*/
-       .unlocked_ioctl = ext4_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = ext4_compat_ioctl,
-#endif
-       .fsync          = ext4_sync_file,
-       .release        = ext4_release_dir,
-};
-
 
 static unsigned char get_dtype(struct super_block *sb, int filetype)
 {
@@ -60,6 +44,26 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
        return (ext4_filetype_table[filetype]);
 }
 
+/**
+ * Check if the given dir-inode refers to an htree-indexed directory
+ * (or a directory which chould potentially get coverted to use htree
+ * indexing).
+ *
+ * Return 1 if it is a dx dir, 0 if not
+ */
+static int is_dx_dir(struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+
+       if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
+                    EXT4_FEATURE_COMPAT_DIR_INDEX) &&
+           ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
+            ((inode->i_size >> sb->s_blocksize_bits) == 1)))
+               return 1;
+
+       return 0;
+}
+
 /*
  * Return 0 if the directory entry is OK, and 1 if there is a problem
  *
@@ -115,18 +119,13 @@ static int ext4_readdir(struct file *filp,
        unsigned int offset;
        int i, stored;
        struct ext4_dir_entry_2 *de;
-       struct super_block *sb;
        int err;
        struct inode *inode = filp->f_path.dentry->d_inode;
+       struct super_block *sb = inode->i_sb;
        int ret = 0;
        int dir_has_error = 0;
 
-       sb = inode->i_sb;
-
-       if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
-                                   EXT4_FEATURE_COMPAT_DIR_INDEX) &&
-           ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
-            ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
+       if (is_dx_dir(inode)) {
                err = ext4_dx_readdir(filp, dirent, filldir);
                if (err != ERR_BAD_DX_DIR) {
                        ret = err;
@@ -254,22 +253,134 @@ out:
        return ret;
 }
 
+static inline int is_32bit_api(void)
+{
+#ifdef CONFIG_COMPAT
+       return is_compat_task();
+#else
+       return (BITS_PER_LONG == 32);
+#endif
+}
+
 /*
  * These functions convert from the major/minor hash to an f_pos
- * value.
+ * value for dx directories
+ *
+ * Upper layer (for example NFS) should specify FMODE_32BITHASH or
+ * FMODE_64BITHASH explicitly. On the other hand, we allow ext4 to be mounted
+ * directly on both 32-bit and 64-bit nodes, under such case, neither
+ * FMODE_32BITHASH nor FMODE_64BITHASH is specified.
+ */
+static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
+{
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return major >> 1;
+       else
+               return ((__u64)(major >> 1) << 32) | (__u64)minor;
+}
+
+static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
+{
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return (pos << 1) & 0xffffffff;
+       else
+               return ((pos >> 32) << 1) & 0xffffffff;
+}
+
+static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
+{
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return 0;
+       else
+               return pos & 0xffffffff;
+}
+
+/*
+ * Return 32- or 64-bit end-of-file for dx directories
+ */
+static inline loff_t ext4_get_htree_eof(struct file *filp)
+{
+       if ((filp->f_mode & FMODE_32BITHASH) ||
+           (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
+               return EXT4_HTREE_EOF_32BIT;
+       else
+               return EXT4_HTREE_EOF_64BIT;
+}
+
+
+/*
+ * ext4_dir_llseek() based on generic_file_llseek() to handle both
+ * non-htree and htree directories, where the "offset" is in terms
+ * of the filename hash value instead of the byte offset.
  *
- * Currently we only use major hash numer.  This is unfortunate, but
- * on 32-bit machines, the same VFS interface is used for lseek and
- * llseek, so if we use the 64 bit offset, then the 32-bit versions of
- * lseek/telldir/seekdir will blow out spectacularly, and from within
- * the ext2 low-level routine, we don't know if we're being called by
- * a 64-bit version of the system call or the 32-bit version of the
- * system call.  Worse yet, NFSv2 only allows for a 32-bit readdir
- * cookie.  Sigh.
+ * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX)
+ *       will be invalid once the directory was converted into a dx directory
  */
-#define hash2pos(major, minor) (major >> 1)
-#define pos2maj_hash(pos)      ((pos << 1) & 0xffffffff)
-#define pos2min_hash(pos)      (0)
+loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin)
+{
+       struct inode *inode = file->f_mapping->host;
+       loff_t ret = -EINVAL;
+       int dx_dir = is_dx_dir(inode);
+
+       mutex_lock(&inode->i_mutex);
+
+       /* NOTE: relative offsets with dx directories might not work
+        *       as expected, as it is difficult to figure out the
+        *       correct offset between dx hashes */
+
+       switch (origin) {
+       case SEEK_END:
+               if (unlikely(offset > 0))
+                       goto out_err; /* not supported for directories */
+
+               /* so only negative offsets are left, does that have a
+                * meaning for directories at all? */
+               if (dx_dir)
+                       offset += ext4_get_htree_eof(file);
+               else
+                       offset += inode->i_size;
+               break;
+       case SEEK_CUR:
+               /*
+                * Here we special-case the lseek(fd, 0, SEEK_CUR)
+                * position-querying operation.  Avoid rewriting the "same"
+                * f_pos value back to the file because a concurrent read(),
+                * write() or lseek() might have altered it
+                */
+               if (offset == 0) {
+                       offset = file->f_pos;
+                       goto out_ok;
+               }
+
+               offset += file->f_pos;
+               break;
+       }
+
+       if (unlikely(offset < 0))
+               goto out_err;
+
+       if (!dx_dir) {
+               if (offset > inode->i_sb->s_maxbytes)
+                       goto out_err;
+       } else if (offset > ext4_get_htree_eof(file))
+               goto out_err;
+
+       /* Special lock needed here? */
+       if (offset != file->f_pos) {
+               file->f_pos = offset;
+               file->f_version = 0;
+       }
+
+out_ok:
+       ret = offset;
+out_err:
+       mutex_unlock(&inode->i_mutex);
+
+       return ret;
+}
 
 /*
  * This structure holds the nodes of the red-black tree used to store
@@ -330,15 +441,16 @@ static void free_rb_tree_fname(struct rb_root *root)
 }
 
 
-static struct dir_private_info *ext4_htree_create_dir_info(loff_t pos)
+static struct dir_private_info *ext4_htree_create_dir_info(struct file *filp,
+                                                          loff_t pos)
 {
        struct dir_private_info *p;
 
        p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
        if (!p)
                return NULL;
-       p->curr_hash = pos2maj_hash(pos);
-       p->curr_minor_hash = pos2min_hash(pos);
+       p->curr_hash = pos2maj_hash(filp, pos);
+       p->curr_minor_hash = pos2min_hash(filp, pos);
        return p;
 }
 
@@ -430,7 +542,7 @@ static int call_filldir(struct file *filp, void *dirent,
                         inode->i_ino, current->comm);
                return 0;
        }
-       curr_pos = hash2pos(fname->hash, fname->minor_hash);
+       curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
        while (fname) {
                error = filldir(dirent, fname->name,
                                fname->name_len, curr_pos,
@@ -455,13 +567,13 @@ static int ext4_dx_readdir(struct file *filp,
        int     ret;
 
        if (!info) {
-               info = ext4_htree_create_dir_info(filp->f_pos);
+               info = ext4_htree_create_dir_info(filp, filp->f_pos);
                if (!info)
                        return -ENOMEM;
                filp->private_data = info;
        }
 
-       if (filp->f_pos == EXT4_HTREE_EOF)
+       if (filp->f_pos == ext4_get_htree_eof(filp))
                return 0;       /* EOF */
 
        /* Some one has messed with f_pos; reset the world */
@@ -469,8 +581,8 @@ static int ext4_dx_readdir(struct file *filp,
                free_rb_tree_fname(&info->root);
                info->curr_node = NULL;
                info->extra_fname = NULL;
-               info->curr_hash = pos2maj_hash(filp->f_pos);
-               info->curr_minor_hash = pos2min_hash(filp->f_pos);
+               info->curr_hash = pos2maj_hash(filp, filp->f_pos);
+               info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
        }
 
        /*
@@ -502,7 +614,7 @@ static int ext4_dx_readdir(struct file *filp,
                        if (ret < 0)
                                return ret;
                        if (ret == 0) {
-                               filp->f_pos = EXT4_HTREE_EOF;
+                               filp->f_pos = ext4_get_htree_eof(filp);
                                break;
                        }
                        info->curr_node = rb_first(&info->root);
@@ -522,7 +634,7 @@ static int ext4_dx_readdir(struct file *filp,
                        info->curr_minor_hash = fname->minor_hash;
                } else {
                        if (info->next_hash == ~0) {
-                               filp->f_pos = EXT4_HTREE_EOF;
+                               filp->f_pos = ext4_get_htree_eof(filp);
                                break;
                        }
                        info->curr_hash = info->next_hash;
@@ -541,3 +653,15 @@ static int ext4_release_dir(struct inode *inode, struct file *filp)
 
        return 0;
 }
+
+const struct file_operations ext4_dir_operations = {
+       .llseek         = ext4_dir_llseek,
+       .read           = generic_read_dir,
+       .readdir        = ext4_readdir,
+       .unlocked_ioctl = ext4_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ext4_compat_ioctl,
+#endif
+       .fsync          = ext4_sync_file,
+       .release        = ext4_release_dir,
+};
index ded731ac8a321d7408e38bafa03d079717fe47a0..ab2594a30f86f8a39a0fc918a0bdc69e1d7c9e0f 100644 (file)
@@ -1623,7 +1623,11 @@ struct dx_hash_info
        u32             *seed;
 };
 
-#define EXT4_HTREE_EOF 0x7fffffff
+
+/* 32 and 64 bit signed EOF for dx directories */
+#define EXT4_HTREE_EOF_32BIT   ((1UL  << (32 - 1)) - 1)
+#define EXT4_HTREE_EOF_64BIT   ((1ULL << (64 - 1)) - 1)
+
 
 /*
  * Control parameters used by ext4_htree_next_block
index ac8f168c8ab435fcd868854cfdbc4d5d0787c6ad..fa8e4911d3545cdc78b1142cf74026785daa0840 100644 (file)
@@ -200,8 +200,8 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
                return -1;
        }
        hash = hash & ~1;
-       if (hash == (EXT4_HTREE_EOF << 1))
-               hash = (EXT4_HTREE_EOF-1) << 1;
+       if (hash == (EXT4_HTREE_EOF_32BIT << 1))
+               hash = (EXT4_HTREE_EOF_32BIT - 1) << 1;
        hinfo->hash = hash;
        hinfo->minor_hash = minor_hash;
        return 0;
index 74cd1f7f1f888947ac6ef3e2f07c7ec60a66a748..dcdeef169a69811cf995cd34c37bbdcb6d79fd52 100644 (file)
@@ -60,6 +60,7 @@ void ext4_ioend_wait(struct inode *inode)
 static void put_io_page(struct ext4_io_page *io_page)
 {
        if (atomic_dec_and_test(&io_page->p_count)) {
+               end_page_writeback(io_page->p_page);
                put_page(io_page->p_page);
                kmem_cache_free(io_page_cachep, io_page);
        }
@@ -233,9 +234,9 @@ static void ext4_end_bio(struct bio *bio, int error)
                        } while (bh != head);
                }
 
-               if (atomic_read(&io_end->pages[i]->p_count) == 1)
-                       end_page_writeback(io_end->pages[i]->p_page);
+               put_io_page(io_end->pages[i]);
        }
+       io_end->num_io_pages = 0;
        inode = io_end->inode;
 
        if (error) {
@@ -427,8 +428,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
         * PageWriteback bit from the page to prevent the system from
         * wedging later on.
         */
-       if (atomic_read(&io_page->p_count) == 1)
-               end_page_writeback(page);
        put_io_page(io_page);
        return ret;
 }
index 22764c7c8382ce607ca5f9ec9b1a2f48e3d15c4e..75e7c1f3a08015dddd314801686faa24188cc055 100644 (file)
@@ -32,20 +32,20 @@ void set_close_on_exec(unsigned int fd, int flag)
        spin_lock(&files->file_lock);
        fdt = files_fdtable(files);
        if (flag)
-               FD_SET(fd, fdt->close_on_exec);
+               __set_close_on_exec(fd, fdt);
        else
-               FD_CLR(fd, fdt->close_on_exec);
+               __clear_close_on_exec(fd, fdt);
        spin_unlock(&files->file_lock);
 }
 
-static int get_close_on_exec(unsigned int fd)
+static bool get_close_on_exec(unsigned int fd)
 {
        struct files_struct *files = current->files;
        struct fdtable *fdt;
-       int res;
+       bool res;
        rcu_read_lock();
        fdt = files_fdtable(files);
-       res = FD_ISSET(fd, fdt->close_on_exec);
+       res = close_on_exec(fd, fdt);
        rcu_read_unlock();
        return res;
 }
@@ -90,15 +90,15 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
        err = -EBUSY;
        fdt = files_fdtable(files);
        tofree = fdt->fd[newfd];
-       if (!tofree && FD_ISSET(newfd, fdt->open_fds))
+       if (!tofree && fd_is_open(newfd, fdt))
                goto out_unlock;
        get_file(file);
        rcu_assign_pointer(fdt->fd[newfd], file);
-       FD_SET(newfd, fdt->open_fds);
+       __set_open_fd(newfd, fdt);
        if (flags & O_CLOEXEC)
-               FD_SET(newfd, fdt->close_on_exec);
+               __set_close_on_exec(newfd, fdt);
        else
-               FD_CLR(newfd, fdt->close_on_exec);
+               __clear_close_on_exec(newfd, fdt);
        spin_unlock(&files->file_lock);
 
        if (tofree)
index 3c426de7203a831ba3e107b10eac1a8f8849b72d..ba3f6053025cf44915ebd5ca42605d3281429d33 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -40,7 +40,7 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */
  */
 static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
 
-static void *alloc_fdmem(unsigned int size)
+static void *alloc_fdmem(size_t size)
 {
        /*
         * Very large allocations can stress page reclaim, so fall back to
@@ -142,7 +142,7 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
 static struct fdtable * alloc_fdtable(unsigned int nr)
 {
        struct fdtable *fdt;
-       char *data;
+       void *data;
 
        /*
         * Figure out how many fds we actually want to support in this fdtable.
@@ -172,14 +172,15 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
        data = alloc_fdmem(nr * sizeof(struct file *));
        if (!data)
                goto out_fdt;
-       fdt->fd = (struct file **)data;
-       data = alloc_fdmem(max_t(unsigned int,
+       fdt->fd = data;
+
+       data = alloc_fdmem(max_t(size_t,
                                 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES));
        if (!data)
                goto out_arr;
-       fdt->open_fds = (fd_set *)data;
+       fdt->open_fds = data;
        data += nr / BITS_PER_BYTE;
-       fdt->close_on_exec = (fd_set *)data;
+       fdt->close_on_exec = data;
        fdt->next = NULL;
 
        return fdt;
@@ -275,11 +276,11 @@ static int count_open_files(struct fdtable *fdt)
        int i;
 
        /* Find the last open fd */
-       for (i = size/(8*sizeof(long)); i > 0; ) {
-               if (fdt->open_fds->fds_bits[--i])
+       for (i = size / BITS_PER_LONG; i > 0; ) {
+               if (fdt->open_fds[--i])
                        break;
        }
-       i = (i+1) * 8 * sizeof(long);
+       i = (i + 1) * BITS_PER_LONG;
        return i;
 }
 
@@ -306,8 +307,8 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
        newf->next_fd = 0;
        new_fdt = &newf->fdtab;
        new_fdt->max_fds = NR_OPEN_DEFAULT;
-       new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init;
-       new_fdt->open_fds = (fd_set *)&newf->open_fds_init;
+       new_fdt->close_on_exec = newf->close_on_exec_init;
+       new_fdt->open_fds = newf->open_fds_init;
        new_fdt->fd = &newf->fd_array[0];
        new_fdt->next = NULL;
 
@@ -350,10 +351,8 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
        old_fds = old_fdt->fd;
        new_fds = new_fdt->fd;
 
-       memcpy(new_fdt->open_fds->fds_bits,
-               old_fdt->open_fds->fds_bits, open_files/8);
-       memcpy(new_fdt->close_on_exec->fds_bits,
-               old_fdt->close_on_exec->fds_bits, open_files/8);
+       memcpy(new_fdt->open_fds, old_fdt->open_fds, open_files / 8);
+       memcpy(new_fdt->close_on_exec, old_fdt->close_on_exec, open_files / 8);
 
        for (i = open_files; i != 0; i--) {
                struct file *f = *old_fds++;
@@ -366,7 +365,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
                         * is partway through open().  So make sure that this
                         * fd is available to the new process.
                         */
-                       FD_CLR(open_files - i, new_fdt->open_fds);
+                       __clear_open_fd(open_files - i, new_fdt);
                }
                rcu_assign_pointer(*new_fds++, f);
        }
@@ -379,11 +378,11 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
        memset(new_fds, 0, size);
 
        if (new_fdt->max_fds > open_files) {
-               int left = (new_fdt->max_fds-open_files)/8;
-               int start = open_files / (8 * sizeof(unsigned long));
+               int left = (new_fdt->max_fds - open_files) / 8;
+               int start = open_files / BITS_PER_LONG;
 
-               memset(&new_fdt->open_fds->fds_bits[start], 0, left);
-               memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
+               memset(&new_fdt->open_fds[start], 0, left);
+               memset(&new_fdt->close_on_exec[start], 0, left);
        }
 
        rcu_assign_pointer(newf->fdt, new_fdt);
@@ -419,8 +418,8 @@ struct files_struct init_files = {
        .fdtab          = {
                .max_fds        = NR_OPEN_DEFAULT,
                .fd             = &init_files.fd_array[0],
-               .close_on_exec  = (fd_set *)&init_files.close_on_exec_init,
-               .open_fds       = (fd_set *)&init_files.open_fds_init,
+               .close_on_exec  = init_files.close_on_exec_init,
+               .open_fds       = init_files.open_fds_init,
        },
        .file_lock      = __SPIN_LOCK_UNLOCKED(init_task.file_lock),
 };
@@ -443,8 +442,7 @@ repeat:
                fd = files->next_fd;
 
        if (fd < fdt->max_fds)
-               fd = find_next_zero_bit(fdt->open_fds->fds_bits,
-                                          fdt->max_fds, fd);
+               fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, fd);
 
        error = expand_files(files, fd);
        if (error < 0)
@@ -460,11 +458,11 @@ repeat:
        if (start <= files->next_fd)
                files->next_fd = fd + 1;
 
-       FD_SET(fd, fdt->open_fds);
+       __set_open_fd(fd, fdt);
        if (flags & O_CLOEXEC)
-               FD_SET(fd, fdt->close_on_exec);
+               __set_close_on_exec(fd, fdt);
        else
-               FD_CLR(fd, fdt->close_on_exec);
+               __clear_close_on_exec(fd, fdt);
        error = fd;
 #if 1
        /* Sanity check */
index 17f557f01cf0dd570dcd112e5d686fa072cd7498..806525a7269c5e7bd7cd864a7350563e792c1858 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/blkdev.h>
 #include <linux/bitops.h>
 #include <trace/events/jbd2.h>
-#include <asm/system.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
index 98ed6dbfe381370710f89109dd0b5a2209a44494..1afb701622b0b17748b4cd7f7d171df139bcc9cc 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 EXPORT_SYMBOL(jbd2_journal_extend);
 EXPORT_SYMBOL(jbd2_journal_stop);
index 2774e1013b34467acc3c1c6bc55f47fcac8d3ca7..f49b9afc443690a2377db100ed7da33452ef98db 100644 (file)
@@ -496,7 +496,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp)       \
        __typeof__(type) num = which_strtol(val, &endp, 0);             \
        if (endp == val || *endp || num < (min) || num > (max))         \
                return -EINVAL;                                         \
-       *((int *) kp->arg) = num;                                       \
+       *((type *) kp->arg) = num;                                      \
        return 0;                                                       \
 }
 
index 64a326418aa272dbda0211e892ddb32b7217eb81..3ff5fcc1528fd21ae18a7a240ec9f2920ec30d32 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/time.h>
 #include <linux/kernel.h>
index 49df0e7f8379149c3f113506afdc5c8ee7db51a4..87484fb8d1773b07e42c6ec63a7ec50533fd0b60 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
index e5d71b27a5b0588be72426a598d80197d042a521..be20a7e171a0f18ebe24d32d0ebed2b4d71a6040 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/memcontrol.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include "ncp_fs.h"
 
index 4a108a0a2a6085e75c4cb42a2564d32013e28bce..da7b5e4ff9ec19adc0c7e53452a87d7cd35a609b 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/nsproxy.h>
 #include <linux/pid_namespace.h>
 
-#include <asm/system.h>
 
 #include "nfs4_fs.h"
 #include "callback.h"
index 9c7f66ac6cc2ad2d40f7eec79f931f205b96a310..481be7f7bdd3b953179a2ab354c9f05fc4773925 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/nfs_page.h>
 #include <linux/sunrpc/clnt.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/atomic.h>
 
index 4fdaaa63cf1c3f0d72ca58088ba312026881aa19..aa9b709fd328d7178cd1c4bdb417fb6f454472af 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/swap.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include "delegation.h"
 #include "internal.h"
index 801d6d830787cf03ce02b2c768d5b56049c120b6..4ca6f5c8038e02dfddb3a8a33dec71a8cb20295f 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/namei.h>
 #include <linux/security.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "nfs4_fs.h"
index 7bb4d13c1cd5ecaa10bbab88b8942ccbd9f9b444..e8bbfa5b35009ae6ff7b2ac576d23615dec1c1c7 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/freezer.h>
 #include <linux/crc32.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "nfs4_fs.h"
index 634c0bcb4fd6878776f9d560e8ad023199b975d4..5acfd9ea8a31390eb0f6b3ab6872f8efc334bc2b 100644 (file)
@@ -793,7 +793,6 @@ filelayout_clear_request_commit(struct nfs_page *req)
        if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags))
                goto out;
        if (list_is_singular(&req->wb_list)) {
-               struct inode *inode = req->wb_context->dentry->d_inode;
                struct pnfs_layout_segment *lseg;
 
                /* From here we can find the bucket, but for the moment,
index e809d2305ebf3a6431c52a6f0a805672365557fb..f82bde005a822435fe8c4e7e20e99a60f3a5764c 100644 (file)
@@ -270,7 +270,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                case 0:
                        return 0;
                case -NFS4ERR_OPENMODE:
-                       if (nfs_have_delegation(inode, FMODE_READ)) {
+                       if (inode && nfs_have_delegation(inode, FMODE_READ)) {
                                nfs_inode_return_delegation(inode);
                                exception->retry = 1;
                                return 0;
@@ -282,10 +282,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_BAD_STATEID:
-                       if (state != NULL)
-                               nfs_remove_bad_delegation(state->inode);
                        if (state == NULL)
                                break;
+                       nfs_remove_bad_delegation(state->inode);
                        nfs4_schedule_stateid_recovery(server, state);
                        goto wait_on_recovery;
                case -NFS4ERR_EXPIRED:
@@ -2290,11 +2289,12 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
                switch (err) {
                case 0:
                case -NFS4ERR_WRONGSEC:
-                       break;
+                       goto out;
                default:
                        err = nfs4_handle_exception(server, err, &exception);
                }
        } while (exception.retry);
+out:
        return err;
 }
 
@@ -3712,7 +3712,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
                if (acl_len > buflen)
                        goto out_free;
                _copy_from_pages(buf, pages, res.acl_data_offset,
-                               res.acl_len);
+                               acl_len);
        }
        ret = acl_len;
 out_free:
@@ -3824,8 +3824,9 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_BAD_STATEID:
-                       if (state != NULL)
-                               nfs_remove_bad_delegation(state->inode);
+                       if (state == NULL)
+                               break;
+                       nfs_remove_bad_delegation(state->inode);
                case -NFS4ERR_OPENMODE:
                        if (state == NULL)
                                break;
@@ -6111,21 +6112,22 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
                return;
 
        switch (task->tk_status) { /* Just ignore these failures */
-       case NFS4ERR_DELEG_REVOKED: /* layout was recalled */
-       case NFS4ERR_BADIOMODE:     /* no IOMODE_RW layout for range */
-       case NFS4ERR_BADLAYOUT:     /* no layout */
-       case NFS4ERR_GRACE:         /* loca_recalim always false */
+       case -NFS4ERR_DELEG_REVOKED: /* layout was recalled */
+       case -NFS4ERR_BADIOMODE:     /* no IOMODE_RW layout for range */
+       case -NFS4ERR_BADLAYOUT:     /* no layout */
+       case -NFS4ERR_GRACE:        /* loca_recalim always false */
                task->tk_status = 0;
-       }
-
-       if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
-               rpc_restart_call_prepare(task);
-               return;
-       }
-
-       if (task->tk_status == 0)
+               break;
+       case 0:
                nfs_post_op_update_inode_force_wcc(data->args.inode,
                                                   data->res.fattr);
+               break;
+       default:
+               if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+                       rpc_restart_call_prepare(task);
+                       return;
+               }
+       }
 }
 
 static void nfs4_layoutcommit_release(void *calldata)
@@ -6229,11 +6231,12 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
                case 0:
                case -NFS4ERR_WRONGSEC:
                case -NFS4ERR_NOTSUPP:
-                       break;
+                       goto out;
                default:
                        err = nfs4_handle_exception(server, err, &exception);
                }
        } while (exception.retry);
+out:
        return err;
 }
 
index cc1f758a7ee1a0234d491da9de8572eb1b45a44f..9a0e8ef4a40948d83d87d7a0898a49d55c3099c1 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/nfs_page.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include "pnfs.h"
 
 #include "nfs4_fs.h"
index ccc4cdb1efe9a9e7842718ef24407557b73b382d..37412f706b32c83d5e0b3a95ae8665038ef43d68 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "nfs4_fs.h"
diff --git a/fs/nfsd/current_stateid.h b/fs/nfsd/current_stateid.h
new file mode 100644 (file)
index 0000000..4123551
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _NFSD4_CURRENT_STATE_H
+#define _NFSD4_CURRENT_STATE_H
+
+#include "state.h"
+#include "xdr4.h"
+
+extern void clear_current_stateid(struct nfsd4_compound_state *cstate);
+/*
+ * functions to set current state id
+ */
+extern void nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *);
+extern void nfsd4_set_openstateid(struct nfsd4_compound_state *, struct nfsd4_open *);
+extern void nfsd4_set_lockstateid(struct nfsd4_compound_state *, struct nfsd4_lock *);
+extern void nfsd4_set_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *);
+
+/*
+ * functions to consume current state id
+ */
+extern void nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *);
+extern void nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *, struct nfsd4_delegreturn *);
+extern void nfsd4_get_freestateid(struct nfsd4_compound_state *, struct nfsd4_free_stateid *);
+extern void nfsd4_get_setattrstateid(struct nfsd4_compound_state *, struct nfsd4_setattr *);
+extern void nfsd4_get_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *);
+extern void nfsd4_get_lockustateid(struct nfsd4_compound_state *, struct nfsd4_locku *);
+extern void nfsd4_get_readstateid(struct nfsd4_compound_state *, struct nfsd4_read *);
+extern void nfsd4_get_writestateid(struct nfsd4_compound_state *, struct nfsd4_write *);
+
+#endif   /* _NFSD4_CURRENT_STATE_H */
index cf8a6bd062fa9dc4eccdf3ecc464d83b2a8a6366..8e9689abbc0c7594fb6aa6cb7fb7735018165162 100644 (file)
@@ -87,7 +87,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
        struct svc_expkey key;
        struct svc_expkey *ek = NULL;
 
-       if (mlen < 1 || mesg[mlen-1] != '\n')
+       if (mesg[mlen - 1] != '\n')
                return -EINVAL;
        mesg[mlen-1] = 0;
 
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
new file mode 100644 (file)
index 0000000..12e0cff
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * per net namespace data structures for nfsd
+ *
+ * Copyright (C) 2012, Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __NFSD_NETNS_H__
+#define __NFSD_NETNS_H__
+
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+struct cld_net;
+
+struct nfsd_net {
+       struct cld_net *cld_net;
+};
+
+extern int nfsd_net_id;
+#endif /* __NFSD_NETNS_H__ */
index 0e262f32ac415a577793c74bb8cf6e7cd8d9202f..c8e9f637153ab3e44ba293f7097e7b32e77d4e54 100644 (file)
@@ -645,7 +645,6 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                .timeout        = &timeparms,
                .program        = &cb_program,
                .version        = 0,
-               .authflavor     = clp->cl_flavor,
                .flags          = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
        };
        struct rpc_clnt *client;
@@ -656,6 +655,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                args.client_name = clp->cl_principal;
                args.prognumber = conn->cb_prog,
                args.protocol = XPRT_TRANSPORT_TCP;
+               args.authflavor = clp->cl_flavor;
                clp->cl_cb_ident = conn->cb_ident;
        } else {
                if (!conn->cb_xprt)
@@ -665,6 +665,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                args.bc_xprt = conn->cb_xprt;
                args.prognumber = clp->cl_cb_session->se_cb_prog;
                args.protocol = XPRT_TRANSPORT_BC_TCP;
+               args.authflavor = RPC_AUTH_UNIX;
        }
        /* Create RPC client */
        client = rpc_create(&args);
@@ -754,9 +755,9 @@ static void do_probe_callback(struct nfs4_client *clp)
  */
 void nfsd4_probe_callback(struct nfs4_client *clp)
 {
-       /* XXX: atomicity?  Also, should we be using cl_cb_flags? */
+       /* XXX: atomicity?  Also, should we be using cl_flags? */
        clp->cl_cb_state = NFSD4_CB_UNKNOWN;
-       set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+       set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
        do_probe_callback(clp);
 }
 
@@ -915,7 +916,7 @@ void nfsd4_destroy_callback_queue(void)
 /* must be called under the state lock */
 void nfsd4_shutdown_callback(struct nfs4_client *clp)
 {
-       set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags);
+       set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags);
        /*
         * Note this won't actually result in a null callback;
         * instead, nfsd4_do_callback_rpc() will detect the killed
@@ -966,15 +967,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
                svc_xprt_put(clp->cl_cb_conn.cb_xprt);
                clp->cl_cb_conn.cb_xprt = NULL;
        }
-       if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
+       if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
                return;
        spin_lock(&clp->cl_lock);
        /*
         * Only serialized callback code is allowed to clear these
         * flags; main nfsd code can only set them:
         */
-       BUG_ON(!clp->cl_cb_flags);
-       clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+       BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK));
+       clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
        memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
        c = __nfsd4_find_backchannel(clp);
        if (c) {
@@ -986,7 +987,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
 
        err = setup_callback_client(clp, &conn, ses);
        if (err) {
-               warn_no_callback_path(clp, err);
+               nfsd4_mark_cb_down(clp, err);
                return;
        }
        /* Yay, the callback channel's back! Restart any callbacks: */
@@ -1000,7 +1001,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
        struct nfs4_client *clp = cb->cb_clp;
        struct rpc_clnt *clnt;
 
-       if (clp->cl_cb_flags)
+       if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
                nfsd4_process_cb_update(cb);
 
        clnt = clp->cl_cb_client;
index 94096273cd6cb37b17aa727b55d62a8c8a75a13d..322d11ce06a452858ed0e547cf1e70e7883c08ee 100644 (file)
 #include "idmap.h"
 #include "nfsd.h"
 
+/*
+ * Turn off idmapping when using AUTH_SYS.
+ */
+static bool nfs4_disable_idmapping = true;
+module_param(nfs4_disable_idmapping, bool, 0644);
+MODULE_PARM_DESC(nfs4_disable_idmapping,
+               "Turn off server's NFSv4 idmapping when using 'sec=sys'");
+
 /*
  * Cache entry
  */
@@ -561,28 +569,65 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
        return ret;
 }
 
+static bool
+numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
+{
+       int ret;
+       char buf[11];
+
+       if (namelen + 1 > sizeof(buf))
+               /* too long to represent a 32-bit id: */
+               return false;
+       /* Just to make sure it's null-terminated: */
+       memcpy(buf, name, namelen);
+       buf[namelen] = '\0';
+       ret = kstrtouint(name, 10, id);
+       return ret == 0;
+}
+
+static __be32
+do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
+{
+       if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS)
+               if (numeric_name_to_id(rqstp, type, name, namelen, id))
+                       return 0;
+               /*
+                * otherwise, fall through and try idmapping, for
+                * backwards compatibility with clients sending names:
+                */
+       return idmap_name_to_id(rqstp, type, name, namelen, id);
+}
+
+static int
+do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
+{
+       if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS)
+               return sprintf(name, "%u", id);
+       return idmap_id_to_name(rqstp, type, id, name);
+}
+
 __be32
 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
                __u32 *id)
 {
-       return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
+       return do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
 }
 
 __be32
 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
                __u32 *id)
 {
-       return idmap_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
+       return do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
 }
 
 int
 nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
 {
-       return idmap_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
+       return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
 }
 
 int
 nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
 {
-       return idmap_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
+       return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
 }
index 896da74ec5634fd92739e0284f5d0768c8f12437..2ed14dfd00a231e9c813b78b3d728bcdfb849b06 100644 (file)
@@ -39,6 +39,7 @@
 #include "cache.h"
 #include "xdr4.h"
 #include "vfs.h"
+#include "current_stateid.h"
 
 #define NFSDDBG_FACILITY               NFSDDBG_PROC
 
@@ -192,10 +193,13 @@ static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
 static __be32
 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
-       struct svc_fh resfh;
+       struct svc_fh *resfh;
        __be32 status;
 
-       fh_init(&resfh, NFS4_FHSIZE);
+       resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
+       if (!resfh)
+               return nfserr_jukebox;
+       fh_init(resfh, NFS4_FHSIZE);
        open->op_truncate = 0;
 
        if (open->op_create) {
@@ -220,7 +224,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                 */
                status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
                                        open->op_fname.len, &open->op_iattr,
-                                       &resfh, open->op_createmode,
+                                       resfh, open->op_createmode,
                                        (u32 *)open->op_verf.data,
                                        &open->op_truncate, &open->op_created);
 
@@ -234,30 +238,29 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                                                FATTR4_WORD1_TIME_MODIFY);
        } else {
                status = nfsd_lookup(rqstp, current_fh,
-                                    open->op_fname.data, open->op_fname.len, &resfh);
+                                    open->op_fname.data, open->op_fname.len, resfh);
                fh_unlock(current_fh);
                if (status)
                        goto out;
-               status = nfsd_check_obj_isreg(&resfh);
+               status = nfsd_check_obj_isreg(resfh);
        }
        if (status)
                goto out;
 
        if (is_create_with_attrs(open) && open->op_acl != NULL)
-               do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval);
-
-       set_change_info(&open->op_cinfo, current_fh);
-       fh_dup2(current_fh, &resfh);
+               do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
 
        /* set reply cache */
        fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
-                       &resfh.fh_handle);
+                       &resfh->fh_handle);
        if (!open->op_created)
-               status = do_open_permission(rqstp, current_fh, open,
+               status = do_open_permission(rqstp, resfh, open,
                                            NFSD_MAY_NOP);
-
+       set_change_info(&open->op_cinfo, current_fh);
+       fh_dup2(current_fh, resfh);
 out:
-       fh_put(&resfh);
+       fh_put(resfh);
+       kfree(resfh);
        return status;
 }
 
@@ -310,16 +313,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
                return nfserr_inval;
 
-       /* We don't yet support WANT bits: */
-       open->op_share_access &= NFS4_SHARE_ACCESS_MASK;
-
        open->op_created = 0;
        /*
         * RFC5661 18.51.3
         * Before RECLAIM_COMPLETE done, server should deny new lock
         */
        if (nfsd4_has_session(cstate) &&
-           !cstate->session->se_client->cl_firststate &&
+           !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
+                     &cstate->session->se_client->cl_flags) &&
            open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
                return nfserr_grace;
 
@@ -452,6 +453,10 @@ nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                return nfserr_restorefh;
 
        fh_dup2(&cstate->current_fh, &cstate->save_fh);
+       if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) {
+               memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t));
+               SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
+       }
        return nfs_ok;
 }
 
@@ -463,6 +468,10 @@ nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                return nfserr_nofilehandle;
 
        fh_dup2(&cstate->save_fh, &cstate->current_fh);
+       if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) {
+               memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t));
+               SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG);
+       }
        return nfs_ok;
 }
 
@@ -481,14 +490,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                           &access->ac_supported);
 }
 
+static void gen_boot_verifier(nfs4_verifier *verifier)
+{
+       __be32 verf[2];
+
+       verf[0] = (__be32)nfssvc_boot.tv_sec;
+       verf[1] = (__be32)nfssvc_boot.tv_usec;
+       memcpy(verifier->data, verf, sizeof(verifier->data));
+}
+
 static __be32
 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
             struct nfsd4_commit *commit)
 {
-       u32 *p = (u32 *)commit->co_verf.data;
-       *p++ = nfssvc_boot.tv_sec;
-       *p++ = nfssvc_boot.tv_usec;
-
+       gen_boot_verifier(&commit->co_verf);
        return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
                             commit->co_count);
 }
@@ -865,7 +880,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        stateid_t *stateid = &write->wr_stateid;
        struct file *filp = NULL;
-       u32 *p;
        __be32 status = nfs_ok;
        unsigned long cnt;
 
@@ -887,9 +901,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        cnt = write->wr_buflen;
        write->wr_how_written = write->wr_stable_how;
-       p = (u32 *)write->wr_verifier.data;
-       *p++ = nfssvc_boot.tv_sec;
-       *p++ = nfssvc_boot.tv_usec;
+       gen_boot_verifier(&write->wr_verifier);
 
        status =  nfsd_write(rqstp, &cstate->current_fh, filp,
                             write->wr_offset, rqstp->rq_vec, write->wr_vlen,
@@ -1000,6 +1012,8 @@ static inline void nfsd4_increment_op_stats(u32 opnum)
 typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
                              void *);
 typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op);
+typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *);
+typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *);
 
 enum nfsd4_op_flags {
        ALLOWED_WITHOUT_FH = 1 << 0,    /* No current filehandle required */
@@ -1025,6 +1039,10 @@ enum nfsd4_op_flags {
         * the v4.0 case).
         */
        OP_CACHEME = 1 << 6,
+       /*
+        * These are ops which clear current state id.
+        */
+       OP_CLEAR_STATEID = 1 << 7,
 };
 
 struct nfsd4_operation {
@@ -1033,11 +1051,15 @@ struct nfsd4_operation {
        char *op_name;
        /* Try to get response size before operation */
        nfsd4op_rsize op_rsize_bop;
+       stateid_setter op_get_currentstateid;
+       stateid_getter op_set_currentstateid;
 };
 
 static struct nfsd4_operation nfsd4_ops[];
 
+#ifdef NFSD_DEBUG
 static const char *nfsd4_op_name(unsigned opnum);
+#endif
 
 /*
  * Enforce NFSv4.1 COMPOUND ordering rules:
@@ -1215,13 +1237,23 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
                if (op->status)
                        goto encode_op;
 
-               if (opdesc->op_func)
+               if (opdesc->op_func) {
+                       if (opdesc->op_get_currentstateid)
+                               opdesc->op_get_currentstateid(cstate, &op->u);
                        op->status = opdesc->op_func(rqstp, cstate, &op->u);
-               else
+               else
                        BUG_ON(op->status == nfs_ok);
 
-               if (!op->status && need_wrongsec_check(rqstp))
-                       op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
+               if (!op->status) {
+                       if (opdesc->op_set_currentstateid)
+                               opdesc->op_set_currentstateid(cstate, &op->u);
+
+                       if (opdesc->op_flags & OP_CLEAR_STATEID)
+                               clear_current_stateid(cstate);
+
+                       if (need_wrongsec_check(rqstp))
+                               op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
+               }
 
 encode_op:
                /* Only from SEQUENCE */
@@ -1413,6 +1445,8 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING,
                .op_name = "OP_CLOSE",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid,
+               .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid,
        },
        [OP_COMMIT] = {
                .op_func = (nfsd4op_func)nfsd4_commit,
@@ -1422,7 +1456,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
        },
        [OP_CREATE] = {
                .op_func = (nfsd4op_func)nfsd4_create,
-               .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
+               .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID,
                .op_name = "OP_CREATE",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize,
        },
@@ -1431,6 +1465,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING,
                .op_name = "OP_DELEGRETURN",
                .op_rsize_bop = nfsd4_only_status_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_delegreturnstateid,
        },
        [OP_GETATTR] = {
                .op_func = (nfsd4op_func)nfsd4_getattr,
@@ -1453,6 +1488,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING,
                .op_name = "OP_LOCK",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize,
+               .op_set_currentstateid = (stateid_setter)nfsd4_set_lockstateid,
        },
        [OP_LOCKT] = {
                .op_func = (nfsd4op_func)nfsd4_lockt,
@@ -1463,15 +1499,16 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING,
                .op_name = "OP_LOCKU",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_lockustateid,
        },
        [OP_LOOKUP] = {
                .op_func = (nfsd4op_func)nfsd4_lookup,
-               .op_flags = OP_HANDLES_WRONGSEC,
+               .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
                .op_name = "OP_LOOKUP",
        },
        [OP_LOOKUPP] = {
                .op_func = (nfsd4op_func)nfsd4_lookupp,
-               .op_flags = OP_HANDLES_WRONGSEC,
+               .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
                .op_name = "OP_LOOKUPP",
        },
        [OP_NVERIFY] = {
@@ -1483,6 +1520,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
                .op_name = "OP_OPEN",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize,
+               .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid,
        },
        [OP_OPEN_CONFIRM] = {
                .op_func = (nfsd4op_func)nfsd4_open_confirm,
@@ -1495,25 +1533,30 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING,
                .op_name = "OP_OPEN_DOWNGRADE",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_opendowngradestateid,
+               .op_set_currentstateid = (stateid_setter)nfsd4_set_opendowngradestateid,
        },
        [OP_PUTFH] = {
                .op_func = (nfsd4op_func)nfsd4_putfh,
                .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
-                               | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
+                               | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
+                               | OP_CLEAR_STATEID,
                .op_name = "OP_PUTFH",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
        },
        [OP_PUTPUBFH] = {
                .op_func = (nfsd4op_func)nfsd4_putrootfh,
                .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
-                               | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
+                               | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
+                               | OP_CLEAR_STATEID,
                .op_name = "OP_PUTPUBFH",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
        },
        [OP_PUTROOTFH] = {
                .op_func = (nfsd4op_func)nfsd4_putrootfh,
                .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
-                               | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
+                               | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
+                               | OP_CLEAR_STATEID,
                .op_name = "OP_PUTROOTFH",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
        },
@@ -1522,6 +1565,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING,
                .op_name = "OP_READ",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid,
        },
        [OP_READDIR] = {
                .op_func = (nfsd4op_func)nfsd4_readdir,
@@ -1576,6 +1620,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_name = "OP_SETATTR",
                .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_setattrstateid,
        },
        [OP_SETCLIENTID] = {
                .op_func = (nfsd4op_func)nfsd4_setclientid,
@@ -1600,6 +1645,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
                .op_name = "OP_WRITE",
                .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
+               .op_get_currentstateid = (stateid_getter)nfsd4_get_writestateid,
        },
        [OP_RELEASE_LOCKOWNER] = {
                .op_func = (nfsd4op_func)nfsd4_release_lockowner,
@@ -1674,12 +1720,14 @@ static struct nfsd4_operation nfsd4_ops[] = {
        },
 };
 
+#ifdef NFSD_DEBUG
 static const char *nfsd4_op_name(unsigned opnum)
 {
        if (opnum < ARRAY_SIZE(nfsd4_ops))
                return nfsd4_ops[opnum].op_name;
        return "unknown_operation";
 }
+#endif
 
 #define nfsd4_voidres                  nfsd4_voidargs
 struct nfsd4_voidargs { int dummy; };
index 0b3e875d1abd5e4cd962d5ed5df29f22c7ca546d..4767429264a25b3e6003953c8d3f1e70627b075d 100644 (file)
@@ -1,5 +1,6 @@
 /*
 *  Copyright (c) 2004 The Regents of the University of Michigan.
+*  Copyright (c) 2012 Jeff Layton <jlayton@redhat.com>
 *  All rights reserved.
 *
 *  Andy Adamson <andros@citi.umich.edu>
 #include <linux/namei.h>
 #include <linux/crypto.h>
 #include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <net/net_namespace.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/nfsd/cld.h>
 
 #include "nfsd.h"
 #include "state.h"
 #include "vfs.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
+/* Declarations */
+struct nfsd4_client_tracking_ops {
+       int (*init)(struct net *);
+       void (*exit)(struct net *);
+       void (*create)(struct nfs4_client *);
+       void (*remove)(struct nfs4_client *);
+       int (*check)(struct nfs4_client *);
+       void (*grace_done)(struct net *, time_t);
+};
+
 /* Globals */
 static struct file *rec_file;
 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
+static struct nfsd4_client_tracking_ops *client_tracking_ops;
 
 static int
 nfs4_save_creds(const struct cred **original_creds)
@@ -117,7 +136,8 @@ out_no_tfm:
        return status;
 }
 
-void nfsd4_create_clid_dir(struct nfs4_client *clp)
+static void
+nfsd4_create_clid_dir(struct nfs4_client *clp)
 {
        const struct cred *original_cred;
        char *dname = clp->cl_recdir;
@@ -126,9 +146,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp)
 
        dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
 
-       if (clp->cl_firststate)
+       if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
                return;
-       clp->cl_firststate = 1;
        if (!rec_file)
                return;
        status = nfs4_save_creds(&original_cred);
@@ -265,19 +284,19 @@ out_unlock:
        return status;
 }
 
-void
+static void
 nfsd4_remove_clid_dir(struct nfs4_client *clp)
 {
        const struct cred *original_cred;
        int status;
 
-       if (!rec_file || !clp->cl_firststate)
+       if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
                return;
 
        status = mnt_want_write_file(rec_file);
        if (status)
                goto out;
-       clp->cl_firststate = 0;
+       clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
 
        status = nfs4_save_creds(&original_cred);
        if (status < 0)
@@ -292,7 +311,6 @@ out:
        if (status)
                printk("NFSD: Failed to remove expired client state directory"
                                " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
-       return;
 }
 
 static int
@@ -311,8 +329,9 @@ purge_old(struct dentry *parent, struct dentry *child)
        return 0;
 }
 
-void
-nfsd4_recdir_purge_old(void) {
+static void
+nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
+{
        int status;
 
        if (!rec_file)
@@ -343,7 +362,7 @@ load_recdir(struct dentry *parent, struct dentry *child)
        return 0;
 }
 
-int
+static int
 nfsd4_recdir_load(void) {
        int status;
 
@@ -361,8 +380,8 @@ nfsd4_recdir_load(void) {
  * Hold reference to the recovery directory.
  */
 
-void
-nfsd4_init_recdir()
+static int
+nfsd4_init_recdir(void)
 {
        const struct cred *original_cred;
        int status;
@@ -377,20 +396,44 @@ nfsd4_init_recdir()
                printk("NFSD: Unable to change credentials to find recovery"
                       " directory: error %d\n",
                       status);
-               return;
+               return status;
        }
 
        rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
        if (IS_ERR(rec_file)) {
                printk("NFSD: unable to find recovery directory %s\n",
                                user_recovery_dirname);
+               status = PTR_ERR(rec_file);
                rec_file = NULL;
        }
 
        nfs4_reset_creds(original_cred);
+       return status;
 }
 
-void
+static int
+nfsd4_load_reboot_recovery_data(struct net *net)
+{
+       int status;
+
+       /* XXX: The legacy code won't work in a container */
+       if (net != &init_net) {
+               WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client "
+                       "tracking in a container!\n");
+               return -EINVAL;
+       }
+
+       nfs4_lock_state();
+       status = nfsd4_init_recdir();
+       if (!status)
+               status = nfsd4_recdir_load();
+       nfs4_unlock_state();
+       if (status)
+               printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
+       return status;
+}
+
+static void
 nfsd4_shutdown_recdir(void)
 {
        if (!rec_file)
@@ -399,6 +442,13 @@ nfsd4_shutdown_recdir(void)
        rec_file = NULL;
 }
 
+static void
+nfsd4_legacy_tracking_exit(struct net *net)
+{
+       nfs4_release_reclaim();
+       nfsd4_shutdown_recdir();
+}
+
 /*
  * Change the NFSv4 recovery directory to recdir.
  */
@@ -425,3 +475,572 @@ nfs4_recoverydir(void)
 {
        return user_recovery_dirname;
 }
+
+static int
+nfsd4_check_legacy_client(struct nfs4_client *clp)
+{
+       /* did we already find that this client is stable? */
+       if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+               return 0;
+
+       /* look for it in the reclaim hashtable otherwise */
+       if (nfsd4_find_reclaim_client(clp)) {
+               set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+               return 0;
+       }
+
+       return -ENOENT;
+}
+
+static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
+       .init           = nfsd4_load_reboot_recovery_data,
+       .exit           = nfsd4_legacy_tracking_exit,
+       .create         = nfsd4_create_clid_dir,
+       .remove         = nfsd4_remove_clid_dir,
+       .check          = nfsd4_check_legacy_client,
+       .grace_done     = nfsd4_recdir_purge_old,
+};
+
+/* Globals */
+#define NFSD_PIPE_DIR          "nfsd"
+#define NFSD_CLD_PIPE          "cld"
+
+/* per-net-ns structure for holding cld upcall info */
+struct cld_net {
+       struct rpc_pipe         *cn_pipe;
+       spinlock_t               cn_lock;
+       struct list_head         cn_list;
+       unsigned int             cn_xid;
+};
+
+struct cld_upcall {
+       struct list_head         cu_list;
+       struct cld_net          *cu_net;
+       struct task_struct      *cu_task;
+       struct cld_msg           cu_msg;
+};
+
+static int
+__cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
+{
+       int ret;
+       struct rpc_pipe_msg msg;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.data = cmsg;
+       msg.len = sizeof(*cmsg);
+
+       /*
+        * Set task state before we queue the upcall. That prevents
+        * wake_up_process in the downcall from racing with schedule.
+        */
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       ret = rpc_queue_upcall(pipe, &msg);
+       if (ret < 0) {
+               set_current_state(TASK_RUNNING);
+               goto out;
+       }
+
+       schedule();
+       set_current_state(TASK_RUNNING);
+
+       if (msg.errno < 0)
+               ret = msg.errno;
+out:
+       return ret;
+}
+
+static int
+cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
+{
+       int ret;
+
+       /*
+        * -EAGAIN occurs when pipe is closed and reopened while there are
+        *  upcalls queued.
+        */
+       do {
+               ret = __cld_pipe_upcall(pipe, cmsg);
+       } while (ret == -EAGAIN);
+
+       return ret;
+}
+
+static ssize_t
+cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+{
+       struct cld_upcall *tmp, *cup;
+       struct cld_msg *cmsg = (struct cld_msg *)src;
+       uint32_t xid;
+       struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info,
+                                               nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+
+       if (mlen != sizeof(*cmsg)) {
+               dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen,
+                       sizeof(*cmsg));
+               return -EINVAL;
+       }
+
+       /* copy just the xid so we can try to find that */
+       if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) {
+               dprintk("%s: error when copying xid from userspace", __func__);
+               return -EFAULT;
+       }
+
+       /* walk the list and find corresponding xid */
+       cup = NULL;
+       spin_lock(&cn->cn_lock);
+       list_for_each_entry(tmp, &cn->cn_list, cu_list) {
+               if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) {
+                       cup = tmp;
+                       list_del_init(&cup->cu_list);
+                       break;
+               }
+       }
+       spin_unlock(&cn->cn_lock);
+
+       /* couldn't find upcall? */
+       if (!cup) {
+               dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
+               return -EFAULT;
+
+       wake_up_process(cup->cu_task);
+       return mlen;
+}
+
+static void
+cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
+{
+       struct cld_msg *cmsg = msg->data;
+       struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
+                                                cu_msg);
+
+       /* errno >= 0 means we got a downcall */
+       if (msg->errno >= 0)
+               return;
+
+       wake_up_process(cup->cu_task);
+}
+
+static const struct rpc_pipe_ops cld_upcall_ops = {
+       .upcall         = rpc_pipe_generic_upcall,
+       .downcall       = cld_pipe_downcall,
+       .destroy_msg    = cld_pipe_destroy_msg,
+};
+
+static struct dentry *
+nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
+{
+       struct dentry *dir, *dentry;
+
+       dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
+       if (dir == NULL)
+               return ERR_PTR(-ENOENT);
+       dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
+       dput(dir);
+       return dentry;
+}
+
+static void
+nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
+{
+       if (pipe->dentry)
+               rpc_unlink(pipe->dentry);
+}
+
+static struct dentry *
+nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
+{
+       struct super_block *sb;
+       struct dentry *dentry;
+
+       sb = rpc_get_sb_net(net);
+       if (!sb)
+               return NULL;
+       dentry = nfsd4_cld_register_sb(sb, pipe);
+       rpc_put_sb_net(net);
+       return dentry;
+}
+
+static void
+nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
+{
+       struct super_block *sb;
+
+       sb = rpc_get_sb_net(net);
+       if (sb) {
+               nfsd4_cld_unregister_sb(pipe);
+               rpc_put_sb_net(net);
+       }
+}
+
+/* Initialize rpc_pipefs pipe for communication with client tracking daemon */
+static int
+nfsd4_init_cld_pipe(struct net *net)
+{
+       int ret;
+       struct dentry *dentry;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       struct cld_net *cn;
+
+       if (nn->cld_net)
+               return 0;
+
+       cn = kzalloc(sizeof(*cn), GFP_KERNEL);
+       if (!cn) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+       if (IS_ERR(cn->cn_pipe)) {
+               ret = PTR_ERR(cn->cn_pipe);
+               goto err;
+       }
+       spin_lock_init(&cn->cn_lock);
+       INIT_LIST_HEAD(&cn->cn_list);
+
+       dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
+       if (IS_ERR(dentry)) {
+               ret = PTR_ERR(dentry);
+               goto err_destroy_data;
+       }
+
+       cn->cn_pipe->dentry = dentry;
+       nn->cld_net = cn;
+       return 0;
+
+err_destroy_data:
+       rpc_destroy_pipe_data(cn->cn_pipe);
+err:
+       kfree(cn);
+       printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
+                       ret);
+       return ret;
+}
+
+static void
+nfsd4_remove_cld_pipe(struct net *net)
+{
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+
+       nfsd4_cld_unregister_net(net, cn->cn_pipe);
+       rpc_destroy_pipe_data(cn->cn_pipe);
+       kfree(nn->cld_net);
+       nn->cld_net = NULL;
+}
+
+static struct cld_upcall *
+alloc_cld_upcall(struct cld_net *cn)
+{
+       struct cld_upcall *new, *tmp;
+
+       new = kzalloc(sizeof(*new), GFP_KERNEL);
+       if (!new)
+               return new;
+
+       /* FIXME: hard cap on number in flight? */
+restart_search:
+       spin_lock(&cn->cn_lock);
+       list_for_each_entry(tmp, &cn->cn_list, cu_list) {
+               if (tmp->cu_msg.cm_xid == cn->cn_xid) {
+                       cn->cn_xid++;
+                       spin_unlock(&cn->cn_lock);
+                       goto restart_search;
+               }
+       }
+       new->cu_task = current;
+       new->cu_msg.cm_vers = CLD_UPCALL_VERSION;
+       put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid);
+       new->cu_net = cn;
+       list_add(&new->cu_list, &cn->cn_list);
+       spin_unlock(&cn->cn_lock);
+
+       dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid);
+
+       return new;
+}
+
+static void
+free_cld_upcall(struct cld_upcall *victim)
+{
+       struct cld_net *cn = victim->cu_net;
+
+       spin_lock(&cn->cn_lock);
+       list_del(&victim->cu_list);
+       spin_unlock(&cn->cn_lock);
+       kfree(victim);
+}
+
+/* Ask daemon to create a new record */
+static void
+nfsd4_cld_create(struct nfs4_client *clp)
+{
+       int ret;
+       struct cld_upcall *cup;
+       /* FIXME: determine net from clp */
+       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+
+       /* Don't upcall if it's already stored */
+       if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+               return;
+
+       cup = alloc_cld_upcall(cn);
+       if (!cup) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       cup->cu_msg.cm_cmd = Cld_Create;
+       cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
+       memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
+                       clp->cl_name.len);
+
+       ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
+       if (!ret) {
+               ret = cup->cu_msg.cm_status;
+               set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+       }
+
+       free_cld_upcall(cup);
+out_err:
+       if (ret)
+               printk(KERN_ERR "NFSD: Unable to create client "
+                               "record on stable storage: %d\n", ret);
+}
+
+/* Ask daemon to create a new record */
+static void
+nfsd4_cld_remove(struct nfs4_client *clp)
+{
+       int ret;
+       struct cld_upcall *cup;
+       /* FIXME: determine net from clp */
+       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+
+       /* Don't upcall if it's already removed */
+       if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+               return;
+
+       cup = alloc_cld_upcall(cn);
+       if (!cup) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       cup->cu_msg.cm_cmd = Cld_Remove;
+       cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
+       memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
+                       clp->cl_name.len);
+
+       ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
+       if (!ret) {
+               ret = cup->cu_msg.cm_status;
+               clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+       }
+
+       free_cld_upcall(cup);
+out_err:
+       if (ret)
+               printk(KERN_ERR "NFSD: Unable to remove client "
+                               "record from stable storage: %d\n", ret);
+}
+
+/* Check for presence of a record, and update its timestamp */
+static int
+nfsd4_cld_check(struct nfs4_client *clp)
+{
+       int ret;
+       struct cld_upcall *cup;
+       /* FIXME: determine net from clp */
+       struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+
+       /* Don't upcall if one was already stored during this grace pd */
+       if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
+               return 0;
+
+       cup = alloc_cld_upcall(cn);
+       if (!cup) {
+               printk(KERN_ERR "NFSD: Unable to check client record on "
+                               "stable storage: %d\n", -ENOMEM);
+               return -ENOMEM;
+       }
+
+       cup->cu_msg.cm_cmd = Cld_Check;
+       cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
+       memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
+                       clp->cl_name.len);
+
+       ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
+       if (!ret) {
+               ret = cup->cu_msg.cm_status;
+               set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
+       }
+
+       free_cld_upcall(cup);
+       return ret;
+}
+
+static void
+nfsd4_cld_grace_done(struct net *net, time_t boot_time)
+{
+       int ret;
+       struct cld_upcall *cup;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+
+       cup = alloc_cld_upcall(cn);
+       if (!cup) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       cup->cu_msg.cm_cmd = Cld_GraceDone;
+       cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time;
+       ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
+       if (!ret)
+               ret = cup->cu_msg.cm_status;
+
+       free_cld_upcall(cup);
+out_err:
+       if (ret)
+               printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
+}
+
+static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
+       .init           = nfsd4_init_cld_pipe,
+       .exit           = nfsd4_remove_cld_pipe,
+       .create         = nfsd4_cld_create,
+       .remove         = nfsd4_cld_remove,
+       .check          = nfsd4_cld_check,
+       .grace_done     = nfsd4_cld_grace_done,
+};
+
+int
+nfsd4_client_tracking_init(struct net *net)
+{
+       int status;
+       struct path path;
+
+       if (!client_tracking_ops) {
+               client_tracking_ops = &nfsd4_cld_tracking_ops;
+               status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
+               if (!status) {
+                       if (S_ISDIR(path.dentry->d_inode->i_mode))
+                               client_tracking_ops =
+                                               &nfsd4_legacy_tracking_ops;
+                       path_put(&path);
+               }
+       }
+
+       status = client_tracking_ops->init(net);
+       if (status) {
+               printk(KERN_WARNING "NFSD: Unable to initialize client "
+                                   "recovery tracking! (%d)\n", status);
+               client_tracking_ops = NULL;
+       }
+       return status;
+}
+
+void
+nfsd4_client_tracking_exit(struct net *net)
+{
+       if (client_tracking_ops) {
+               client_tracking_ops->exit(net);
+               client_tracking_ops = NULL;
+       }
+}
+
+void
+nfsd4_client_record_create(struct nfs4_client *clp)
+{
+       if (client_tracking_ops)
+               client_tracking_ops->create(clp);
+}
+
+void
+nfsd4_client_record_remove(struct nfs4_client *clp)
+{
+       if (client_tracking_ops)
+               client_tracking_ops->remove(clp);
+}
+
+int
+nfsd4_client_record_check(struct nfs4_client *clp)
+{
+       if (client_tracking_ops)
+               return client_tracking_ops->check(clp);
+
+       return -EOPNOTSUPP;
+}
+
+void
+nfsd4_record_grace_done(struct net *net, time_t boot_time)
+{
+       if (client_tracking_ops)
+               client_tracking_ops->grace_done(net, boot_time);
+}
+
+static int
+rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
+{
+       struct super_block *sb = ptr;
+       struct net *net = sb->s_fs_info;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       struct cld_net *cn = nn->cld_net;
+       struct dentry *dentry;
+       int ret = 0;
+
+       if (!try_module_get(THIS_MODULE))
+               return 0;
+
+       if (!cn) {
+               module_put(THIS_MODULE);
+               return 0;
+       }
+
+       switch (event) {
+       case RPC_PIPEFS_MOUNT:
+               dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
+               if (IS_ERR(dentry)) {
+                       ret = PTR_ERR(dentry);
+                       break;
+               }
+               cn->cn_pipe->dentry = dentry;
+               break;
+       case RPC_PIPEFS_UMOUNT:
+               if (cn->cn_pipe->dentry)
+                       nfsd4_cld_unregister_sb(cn->cn_pipe);
+               break;
+       default:
+               ret = -ENOTSUPP;
+               break;
+       }
+       module_put(THIS_MODULE);
+       return ret;
+}
+
+struct notifier_block nfsd4_cld_block = {
+       .notifier_call = rpc_pipefs_event,
+};
+
+int
+register_cld_notifier(void)
+{
+       return rpc_pipefs_notifier_register(&nfsd4_cld_block);
+}
+
+void
+unregister_cld_notifier(void)
+{
+       rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
+}
index c5cddd659429f33b371ea03a3d920808911ce8f1..1841f8bf845e7440bba605f25357a512a8a5b0b0 100644 (file)
@@ -58,11 +58,15 @@ static const stateid_t one_stateid = {
 static const stateid_t zero_stateid = {
        /* all fields zero */
 };
+static const stateid_t currentstateid = {
+       .si_generation = 1,
+};
 
 static u64 current_sessionid = 1;
 
 #define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t)))
 #define ONE_STATEID(stateid)  (!memcmp((stateid), &one_stateid, sizeof(stateid_t)))
+#define CURRENT_STATEID(stateid) (!memcmp((stateid), &currentstateid, sizeof(stateid_t)))
 
 /* forward declarations */
 static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner);
@@ -91,6 +95,19 @@ nfs4_lock_state(void)
        mutex_lock(&client_mutex);
 }
 
+static void free_session(struct kref *);
+
+/* Must be called under the client_lock */
+static void nfsd4_put_session_locked(struct nfsd4_session *ses)
+{
+       kref_put(&ses->se_ref, free_session);
+}
+
+static void nfsd4_get_session(struct nfsd4_session *ses)
+{
+       kref_get(&ses->se_ref);
+}
+
 void
 nfs4_unlock_state(void)
 {
@@ -605,12 +622,20 @@ hash_sessionid(struct nfs4_sessionid *sessionid)
        return sid->sequence % SESSION_HASH_SIZE;
 }
 
+#ifdef NFSD_DEBUG
 static inline void
 dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
 {
        u32 *ptr = (u32 *)(&sessionid->data[0]);
        dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]);
 }
+#else
+static inline void
+dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
+{
+}
+#endif
+
 
 static void
 gen_sessionid(struct nfsd4_session *ses)
@@ -832,11 +857,12 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
        spin_unlock(&clp->cl_lock);
 }
 
-void free_session(struct kref *kref)
+static void free_session(struct kref *kref)
 {
        struct nfsd4_session *ses;
        int mem;
 
+       BUG_ON(!spin_is_locked(&client_lock));
        ses = container_of(kref, struct nfsd4_session, se_ref);
        nfsd4_del_conns(ses);
        spin_lock(&nfsd_drc_lock);
@@ -847,6 +873,13 @@ void free_session(struct kref *kref)
        kfree(ses);
 }
 
+void nfsd4_put_session(struct nfsd4_session *ses)
+{
+       spin_lock(&client_lock);
+       nfsd4_put_session_locked(ses);
+       spin_unlock(&client_lock);
+}
+
 static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
 {
        struct nfsd4_session *new;
@@ -894,7 +927,9 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
        status = nfsd4_new_conn_from_crses(rqstp, new);
        /* whoops: benny points out, status is ignored! (err, or bogus) */
        if (status) {
+               spin_lock(&client_lock);
                free_session(&new->se_ref);
+               spin_unlock(&client_lock);
                return NULL;
        }
        if (cses->flags & SESSION4_BACK_CHAN) {
@@ -1006,12 +1041,13 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
 static inline void
 free_client(struct nfs4_client *clp)
 {
+       BUG_ON(!spin_is_locked(&client_lock));
        while (!list_empty(&clp->cl_sessions)) {
                struct nfsd4_session *ses;
                ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
                                se_perclnt);
                list_del(&ses->se_perclnt);
-               nfsd4_put_session(ses);
+               nfsd4_put_session_locked(ses);
        }
        if (clp->cl_cred.cr_group_info)
                put_group_info(clp->cl_cred.cr_group_info);
@@ -1138,12 +1174,12 @@ static void gen_clid(struct nfs4_client *clp)
 
 static void gen_confirm(struct nfs4_client *clp)
 {
+       __be32 verf[2];
        static u32 i;
-       u32 *p;
 
-       p = (u32 *)clp->cl_confirm.data;
-       *p++ = get_seconds();
-       *p++ = i++;
+       verf[0] = (__be32)get_seconds();
+       verf[1] = (__be32)i++;
+       memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
 }
 
 static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
@@ -1180,7 +1216,9 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        if (princ) {
                clp->cl_principal = kstrdup(princ, GFP_KERNEL);
                if (clp->cl_principal == NULL) {
+                       spin_lock(&client_lock);
                        free_client(clp);
+                       spin_unlock(&client_lock);
                        return NULL;
                }
        }
@@ -1347,6 +1385,7 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
        slot->sl_opcnt = resp->opcnt;
        slot->sl_status = resp->cstate.status;
 
+       slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
        if (nfsd4_not_cached(resp)) {
                slot->sl_datalen = 0;
                return;
@@ -1374,15 +1413,12 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,
        struct nfsd4_op *op;
        struct nfsd4_slot *slot = resp->cstate.slot;
 
-       dprintk("--> %s resp->opcnt %d cachethis %u \n", __func__,
-               resp->opcnt, resp->cstate.slot->sl_cachethis);
-
        /* Encode the replayed sequence operation */
        op = &args->ops[resp->opcnt - 1];
        nfsd4_encode_operation(resp, op);
 
        /* Return nfserr_retry_uncached_rep in next operation. */
-       if (args->opcnt > 1 && slot->sl_cachethis == 0) {
+       if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) {
                op = &args->ops[resp->opcnt++];
                op->status = nfserr_retry_uncached_rep;
                nfsd4_encode_operation(resp, op);
@@ -1575,16 +1611,11 @@ check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse)
                else
                        return nfserr_seq_misordered;
        }
-       /* Normal */
+       /* Note unsigned 32-bit arithmetic handles wraparound: */
        if (likely(seqid == slot_seqid + 1))
                return nfs_ok;
-       /* Replay */
        if (seqid == slot_seqid)
                return nfserr_replay_cache;
-       /* Wraparound */
-       if (seqid == 1 && (slot_seqid + 1) == 0)
-               return nfs_ok;
-       /* Misordered replay or misordered new request */
        return nfserr_seq_misordered;
 }
 
@@ -1815,9 +1846,10 @@ nfsd4_destroy_session(struct svc_rqst *r,
        nfsd4_probe_callback_sync(ses->se_client);
        nfs4_unlock_state();
 
+       spin_lock(&client_lock);
        nfsd4_del_conns(ses);
-
-       nfsd4_put_session(ses);
+       nfsd4_put_session_locked(ses);
+       spin_unlock(&client_lock);
        status = nfs_ok;
 out:
        dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -1921,8 +1953,12 @@ nfsd4_sequence(struct svc_rqst *rqstp,
         * sr_highest_slotid and the sr_target_slot id to maxslots */
        seq->maxslots = session->se_fchannel.maxreqs;
 
-       status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_inuse);
+       status = check_slot_seqid(seq->seqid, slot->sl_seqid,
+                                       slot->sl_flags & NFSD4_SLOT_INUSE);
        if (status == nfserr_replay_cache) {
+               status = nfserr_seq_misordered;
+               if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
+                       goto out;
                cstate->slot = slot;
                cstate->session = session;
                /* Return the cached reply status and set cstate->status
@@ -1938,9 +1974,12 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        conn = NULL;
 
        /* Success! bump slot seqid */
-       slot->sl_inuse = true;
        slot->sl_seqid = seq->seqid;
-       slot->sl_cachethis = seq->cachethis;
+       slot->sl_flags |= NFSD4_SLOT_INUSE;
+       if (seq->cachethis)
+               slot->sl_flags |= NFSD4_SLOT_CACHETHIS;
+       else
+               slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
 
        cstate->slot = slot;
        cstate->session = session;
@@ -2030,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 
        nfs4_lock_state();
        status = nfserr_complete_already;
-       if (cstate->session->se_client->cl_firststate)
+       if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
+                            &cstate->session->se_client->cl_flags))
                goto out;
 
        status = nfserr_stale_clientid;
@@ -2045,7 +2085,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
                goto out;
 
        status = nfs_ok;
-       nfsd4_create_clid_dir(cstate->session->se_client);
+       nfsd4_client_record_create(cstate->session->se_client);
 out:
        nfs4_unlock_state();
        return status;
@@ -2240,7 +2280,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                        conf = find_confirmed_client_by_str(unconf->cl_recdir,
                                                            hash);
                        if (conf) {
-                               nfsd4_remove_clid_dir(conf);
+                               nfsd4_client_record_remove(conf);
                                expire_client(conf);
                        }
                        move_to_confirmed(unconf);
@@ -2633,8 +2673,6 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
 
 static int share_access_to_flags(u32 share_access)
 {
-       share_access &= ~NFS4_SHARE_WANT_MASK;
-
        return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE;
 }
 
@@ -2776,10 +2814,9 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
 
 
 static void
-nfs4_set_claim_prev(struct nfsd4_open *open)
+nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
 {
        open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
-       open->op_openowner->oo_owner.so_client->cl_firststate = 1;
 }
 
 /* Should we give out recallable state?: */
@@ -2855,6 +2892,27 @@ static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag)
        return 0;
 }
 
+static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
+{
+       open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
+       if (status == -EAGAIN)
+               open->op_why_no_deleg = WND4_CONTENTION;
+       else {
+               open->op_why_no_deleg = WND4_RESOURCE;
+               switch (open->op_deleg_want) {
+               case NFS4_SHARE_WANT_READ_DELEG:
+               case NFS4_SHARE_WANT_WRITE_DELEG:
+               case NFS4_SHARE_WANT_ANY_DELEG:
+                       break;
+               case NFS4_SHARE_WANT_CANCEL:
+                       open->op_why_no_deleg = WND4_CANCELLED;
+                       break;
+               case NFS4_SHARE_WANT_NO_DELEG:
+                       BUG();  /* not supposed to get here */
+               }
+       }
+}
+
 /*
  * Attempt to hand out a delegation.
  */
@@ -2864,7 +2922,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
        struct nfs4_delegation *dp;
        struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
        int cb_up;
-       int status, flag = 0;
+       int status = 0, flag = 0;
 
        cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
        flag = NFS4_OPEN_DELEGATE_NONE;
@@ -2905,11 +2963,16 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
        dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
                STATEID_VAL(&dp->dl_stid.sc_stateid));
 out:
-       if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
-                       && flag == NFS4_OPEN_DELEGATE_NONE
-                       && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
-               dprintk("NFSD: WARNING: refusing delegation reclaim\n");
        open->op_delegate_type = flag;
+       if (flag == NFS4_OPEN_DELEGATE_NONE) {
+               if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
+                   open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
+                       dprintk("NFSD: WARNING: refusing delegation reclaim\n");
+
+               /* 4.1 client asking for a delegation? */
+               if (open->op_deleg_want)
+                       nfsd4_open_deleg_none_ext(open, status);
+       }
        return;
 out_free:
        nfs4_put_delegation(dp);
@@ -2918,6 +2981,24 @@ out_no_deleg:
        goto out;
 }
 
+static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
+                                       struct nfs4_delegation *dp)
+{
+       if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG &&
+           dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
+               open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
+               open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE;
+       } else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG &&
+                  dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
+               open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
+               open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE;
+       }
+       /* Otherwise the client must be confused wanting a delegation
+        * it already has, therefore we don't return
+        * NFS4_OPEN_DELEGATE_NONE_EXT and reason.
+        */
+}
+
 /*
  * called with nfs4_lock_state() held.
  */
@@ -2979,24 +3060,36 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        update_stateid(&stp->st_stid.sc_stateid);
        memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
 
-       if (nfsd4_has_session(&resp->cstate))
+       if (nfsd4_has_session(&resp->cstate)) {
                open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
 
+               if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
+                       open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
+                       open->op_why_no_deleg = WND4_NOT_WANTED;
+                       goto nodeleg;
+               }
+       }
+
        /*
        * Attempt to hand out a delegation. No error return, because the
        * OPEN succeeds even if we fail.
        */
        nfs4_open_delegation(current_fh, open, stp);
-
+nodeleg:
        status = nfs_ok;
 
        dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
                STATEID_VAL(&stp->st_stid.sc_stateid));
 out:
+       /* 4.1 client trying to upgrade/downgrade delegation? */
+       if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
+           open->op_deleg_want)
+               nfsd4_deleg_xgrade_none_ext(open, dp);
+
        if (fp)
                put_nfs4_file(fp);
        if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
-               nfs4_set_claim_prev(open);
+               nfs4_set_claim_prev(open, nfsd4_has_session(&resp->cstate));
        /*
        * To finish the open response, we just need to set the rflags.
        */
@@ -3066,7 +3159,7 @@ static void
 nfsd4_end_grace(void)
 {
        dprintk("NFSD: end of grace period\n");
-       nfsd4_recdir_purge_old();
+       nfsd4_record_grace_done(&init_net, boot_time);
        locks_end_grace(&nfsd4_manager);
        /*
         * Now that every NFSv4 client has had the chance to recover and
@@ -3115,7 +3208,7 @@ nfs4_laundromat(void)
                clp = list_entry(pos, struct nfs4_client, cl_lru);
                dprintk("NFSD: purging unused client (clientid %08x)\n",
                        clp->cl_clientid.cl_id);
-               nfsd4_remove_clid_dir(clp);
+               nfsd4_client_record_remove(clp);
                expire_client(clp);
        }
        spin_lock(&recall_lock);
@@ -3400,7 +3493,14 @@ __be32
 nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                   struct nfsd4_test_stateid *test_stateid)
 {
-       /* real work is done during encoding */
+       struct nfsd4_test_stateid_id *stateid;
+       struct nfs4_client *cl = cstate->session->se_client;
+
+       nfs4_lock_state();
+       list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
+               stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid);
+       nfs4_unlock_state();
+
        return nfs_ok;
 }
 
@@ -3539,7 +3639,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
                __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
 
-       nfsd4_create_clid_dir(oo->oo_owner.so_client);
+       nfsd4_client_record_create(oo->oo_owner.so_client);
        status = nfs_ok;
 out:
        if (!cstate->replay_owner)
@@ -3596,7 +3696,9 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
                        cstate->current_fh.fh_dentry->d_name.name);
 
        /* We don't yet support WANT bits: */
-       od->od_share_access &= NFS4_SHARE_ACCESS_MASK;
+       if (od->od_deleg_want)
+               dprintk("NFSD: %s: od_deleg_want=0x%x ignored\n", __func__,
+                       od->od_deleg_want);
 
        nfs4_lock_state();
        status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
@@ -4353,7 +4455,9 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
        struct nfs4_client *clp;
 
        clp = find_confirmed_client_by_str(name, strhashval);
-       return clp ? 1 : 0;
+       if (!clp)
+               return 0;
+       return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
 }
 
 /*
@@ -4377,7 +4481,7 @@ nfs4_client_to_reclaim(const char *name)
        return 1;
 }
 
-static void
+void
 nfs4_release_reclaim(void)
 {
        struct nfs4_client_reclaim *crp = NULL;
@@ -4397,19 +4501,12 @@ nfs4_release_reclaim(void)
 
 /*
  * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
-static struct nfs4_client_reclaim *
-nfs4_find_reclaim_client(clientid_t *clid)
+struct nfs4_client_reclaim *
+nfsd4_find_reclaim_client(struct nfs4_client *clp)
 {
        unsigned int strhashval;
-       struct nfs4_client *clp;
        struct nfs4_client_reclaim *crp = NULL;
 
-
-       /* find clientid in conf_id_hashtbl */
-       clp = find_confirmed_client(clid);
-       if (clp == NULL)
-               return NULL;
-
        dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
                            clp->cl_name.len, clp->cl_name.data,
                            clp->cl_recdir);
@@ -4430,7 +4527,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
 __be32
 nfs4_check_open_reclaim(clientid_t *clid)
 {
-       return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
+       struct nfs4_client *clp;
+
+       /* find clientid in conf_id_hashtbl */
+       clp = find_confirmed_client(clid);
+       if (clp == NULL)
+               return nfserr_reclaim_bad;
+
+       return nfsd4_client_record_check(clp) ? nfserr_reclaim_bad : nfs_ok;
 }
 
 #ifdef CONFIG_NFSD_FAULT_INJECTION
@@ -4442,7 +4546,7 @@ void nfsd_forget_clients(u64 num)
 
        nfs4_lock_state();
        list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
-               nfsd4_remove_clid_dir(clp);
+               nfsd4_client_record_remove(clp);
                expire_client(clp);
                if (++count == num)
                        break;
@@ -4577,19 +4681,6 @@ nfs4_state_init(void)
        reclaim_str_hashtbl_size = 0;
 }
 
-static void
-nfsd4_load_reboot_recovery_data(void)
-{
-       int status;
-
-       nfs4_lock_state();
-       nfsd4_init_recdir();
-       status = nfsd4_recdir_load();
-       nfs4_unlock_state();
-       if (status)
-               printk("NFSD: Failure reading reboot recovery data\n");
-}
-
 /*
  * Since the lifetime of a delegation isn't limited to that of an open, a
  * client may quite reasonably hang on to a delegation as long as it has
@@ -4613,21 +4704,34 @@ set_max_delegations(void)
 
 /* initialization to perform when the nfsd service is started: */
 
-static int
-__nfs4_state_start(void)
+int
+nfs4_state_start(void)
 {
        int ret;
 
+       /*
+        * FIXME: For now, we hang most of the pernet global stuff off of
+        * init_net until nfsd is fully containerized. Eventually, we'll
+        * need to pass a net pointer into this function, take a reference
+        * to that instead and then do most of the rest of this on a per-net
+        * basis.
+        */
+       get_net(&init_net);
+       nfsd4_client_tracking_init(&init_net);
        boot_time = get_seconds();
        locks_start_grace(&nfsd4_manager);
        printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
               nfsd4_grace);
        ret = set_callback_cred();
-       if (ret)
-               return -ENOMEM;
+       if (ret) {
+               ret = -ENOMEM;
+               goto out_recovery;
+       }
        laundry_wq = create_singlethread_workqueue("nfsd4");
-       if (laundry_wq == NULL)
-               return -ENOMEM;
+       if (laundry_wq == NULL) {
+               ret = -ENOMEM;
+               goto out_recovery;
+       }
        ret = nfsd4_create_callback_queue();
        if (ret)
                goto out_free_laundry;
@@ -4636,16 +4740,12 @@ __nfs4_state_start(void)
        return 0;
 out_free_laundry:
        destroy_workqueue(laundry_wq);
+out_recovery:
+       nfsd4_client_tracking_exit(&init_net);
+       put_net(&init_net);
        return ret;
 }
 
-int
-nfs4_state_start(void)
-{
-       nfsd4_load_reboot_recovery_data();
-       return __nfs4_state_start();
-}
-
 static void
 __nfs4_state_shutdown(void)
 {
@@ -4676,7 +4776,8 @@ __nfs4_state_shutdown(void)
                unhash_delegation(dp);
        }
 
-       nfsd4_shutdown_recdir();
+       nfsd4_client_tracking_exit(&init_net);
+       put_net(&init_net);
 }
 
 void
@@ -4686,8 +4787,108 @@ nfs4_state_shutdown(void)
        destroy_workqueue(laundry_wq);
        locks_end_grace(&nfsd4_manager);
        nfs4_lock_state();
-       nfs4_release_reclaim();
        __nfs4_state_shutdown();
        nfs4_unlock_state();
        nfsd4_destroy_callback_queue();
 }
+
+static void
+get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
+{
+       if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG) && CURRENT_STATEID(stateid))
+               memcpy(stateid, &cstate->current_stateid, sizeof(stateid_t));
+}
+
+static void
+put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
+{
+       if (cstate->minorversion) {
+               memcpy(&cstate->current_stateid, stateid, sizeof(stateid_t));
+               SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
+       }
+}
+
+void
+clear_current_stateid(struct nfsd4_compound_state *cstate)
+{
+       CLEAR_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
+}
+
+/*
+ * functions to set current state id
+ */
+void
+nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp)
+{
+       put_stateid(cstate, &odp->od_stateid);
+}
+
+void
+nfsd4_set_openstateid(struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
+{
+       put_stateid(cstate, &open->op_stateid);
+}
+
+void
+nfsd4_set_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
+{
+       put_stateid(cstate, &close->cl_stateid);
+}
+
+void
+nfsd4_set_lockstateid(struct nfsd4_compound_state *cstate, struct nfsd4_lock *lock)
+{
+       put_stateid(cstate, &lock->lk_resp_stateid);
+}
+
+/*
+ * functions to consume current state id
+ */
+
+void
+nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp)
+{
+       get_stateid(cstate, &odp->od_stateid);
+}
+
+void
+nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *cstate, struct nfsd4_delegreturn *drp)
+{
+       get_stateid(cstate, &drp->dr_stateid);
+}
+
+void
+nfsd4_get_freestateid(struct nfsd4_compound_state *cstate, struct nfsd4_free_stateid *fsp)
+{
+       get_stateid(cstate, &fsp->fr_stateid);
+}
+
+void
+nfsd4_get_setattrstateid(struct nfsd4_compound_state *cstate, struct nfsd4_setattr *setattr)
+{
+       get_stateid(cstate, &setattr->sa_stateid);
+}
+
+void
+nfsd4_get_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
+{
+       get_stateid(cstate, &close->cl_stateid);
+}
+
+void
+nfsd4_get_lockustateid(struct nfsd4_compound_state *cstate, struct nfsd4_locku *locku)
+{
+       get_stateid(cstate, &locku->lu_stateid);
+}
+
+void
+nfsd4_get_readstateid(struct nfsd4_compound_state *cstate, struct nfsd4_read *read)
+{
+       get_stateid(cstate, &read->rd_stateid);
+}
+
+void
+nfsd4_get_writestateid(struct nfsd4_compound_state *cstate, struct nfsd4_write *write)
+{
+       get_stateid(cstate, &write->wr_stateid);
+}
index 0ec5a1b9700e5e8d59196cfa387f608aa5c7f0ce..bcd8904ab1e36dd807f26379392000fb114f9bc6 100644 (file)
@@ -133,22 +133,6 @@ xdr_error:                                 \
        }                                       \
 } while (0)
 
-static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
-{
-       savep->p        = argp->p;
-       savep->end      = argp->end;
-       savep->pagelen  = argp->pagelen;
-       savep->pagelist = argp->pagelist;
-}
-
-static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
-{
-       argp->p        = savep->p;
-       argp->end      = savep->end;
-       argp->pagelen  = savep->pagelen;
-       argp->pagelist = savep->pagelist;
-}
-
 static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
 {
        /* We want more bytes than seem to be available.
@@ -638,14 +622,18 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
        DECODE_TAIL;
 }
 
-static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x)
+static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
 {
        __be32 *p;
        u32 w;
 
        READ_BUF(4);
        READ32(w);
-       *x = w;
+       *share_access = w & NFS4_SHARE_ACCESS_MASK;
+       *deleg_want = w & NFS4_SHARE_WANT_MASK;
+       if (deleg_when)
+               *deleg_when = w & NFS4_SHARE_WHEN_MASK;
+
        switch (w & NFS4_SHARE_ACCESS_MASK) {
        case NFS4_SHARE_ACCESS_READ:
        case NFS4_SHARE_ACCESS_WRITE:
@@ -673,6 +661,9 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x)
        w &= ~NFS4_SHARE_WANT_MASK;
        if (!w)
                return nfs_ok;
+
+       if (!deleg_when)        /* open_downgrade */
+               return nfserr_inval;
        switch (w) {
        case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL:
        case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED:
@@ -719,6 +710,7 @@ static __be32
 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 {
        DECODE_HEAD;
+       u32 dummy;
 
        memset(open->op_bmval, 0, sizeof(open->op_bmval));
        open->op_iattr.ia_valid = 0;
@@ -727,7 +719,9 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
        /* seqid, share_access, share_deny, clientid, ownerlen */
        READ_BUF(4);
        READ32(open->op_seqid);
-       status = nfsd4_decode_share_access(argp, &open->op_share_access);
+       /* decode, yet ignore deleg_when until supported */
+       status = nfsd4_decode_share_access(argp, &open->op_share_access,
+                                          &open->op_deleg_want, &dummy);
        if (status)
                goto xdr_error;
        status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
@@ -755,14 +749,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
                                goto out;
                        break;
                case NFS4_CREATE_EXCLUSIVE:
-                       READ_BUF(8);
-                       COPYMEM(open->op_verf.data, 8);
+                       READ_BUF(NFS4_VERIFIER_SIZE);
+                       COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
                        break;
                case NFS4_CREATE_EXCLUSIVE4_1:
                        if (argp->minorversion < 1)
                                goto xdr_error;
-                       READ_BUF(8);
-                       COPYMEM(open->op_verf.data, 8);
+                       READ_BUF(NFS4_VERIFIER_SIZE);
+                       COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
                        status = nfsd4_decode_fattr(argp, open->op_bmval,
                                &open->op_iattr, &open->op_acl);
                        if (status)
@@ -848,7 +842,8 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
                return status;
        READ_BUF(4);
        READ32(open_down->od_seqid);
-       status = nfsd4_decode_share_access(argp, &open_down->od_share_access);
+       status = nfsd4_decode_share_access(argp, &open_down->od_share_access,
+                                          &open_down->od_deleg_want, NULL);
        if (status)
                return status;
        status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
@@ -994,8 +989,8 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
 {
        DECODE_HEAD;
 
-       READ_BUF(8);
-       COPYMEM(setclientid->se_verf.data, 8);
+       READ_BUF(NFS4_VERIFIER_SIZE);
+       COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
 
        status = nfsd4_decode_opaque(argp, &setclientid->se_name);
        if (status)
@@ -1020,9 +1015,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
 {
        DECODE_HEAD;
 
-       READ_BUF(8 + sizeof(nfs4_verifier));
+       READ_BUF(8 + NFS4_VERIFIER_SIZE);
        COPYMEM(&scd_c->sc_clientid, 8);
-       COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
+       COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
 
        DECODE_TAIL;
 }
@@ -1385,26 +1380,29 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
 {
-       unsigned int nbytes;
-       stateid_t si;
        int i;
-       __be32 *p;
-       __be32 status;
+       __be32 *p, status;
+       struct nfsd4_test_stateid_id *stateid;
 
        READ_BUF(4);
        test_stateid->ts_num_ids = ntohl(*p++);
 
-       nbytes = test_stateid->ts_num_ids * sizeof(stateid_t);
-       if (nbytes > (u32)((char *)argp->end - (char *)argp->p))
-               goto xdr_error;
-
-       test_stateid->ts_saved_args = argp;
-       save_buf(argp, &test_stateid->ts_savedp);
+       INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
 
        for (i = 0; i < test_stateid->ts_num_ids; i++) {
-               status = nfsd4_decode_stateid(argp, &si);
+               stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL);
+               if (!stateid) {
+                       status = PTR_ERR(stateid);
+                       goto out;
+               }
+
+               defer_free(argp, kfree, stateid);
+               INIT_LIST_HEAD(&stateid->ts_id_list);
+               list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
+
+               status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid);
                if (status)
-                       return status;
+                       goto out;
        }
 
        status = 0;
@@ -2661,8 +2659,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
        __be32 *p;
 
        if (!nfserr) {
-               RESERVE_SPACE(8);
-               WRITEMEM(commit->co_verf.data, 8);
+               RESERVE_SPACE(NFS4_VERIFIER_SIZE);
+               WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE);
                ADJUST_ARGS();
        }
        return nfserr;
@@ -2851,6 +2849,20 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
                WRITE32(0);   /* XXX: is NULL principal ok? */
                ADJUST_ARGS();
                break;
+       case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */
+               switch (open->op_why_no_deleg) {
+               case WND4_CONTENTION:
+               case WND4_RESOURCE:
+                       RESERVE_SPACE(8);
+                       WRITE32(open->op_why_no_deleg);
+                       WRITE32(0);     /* deleg signaling not supported yet */
+                       break;
+               default:
+                       RESERVE_SPACE(4);
+                       WRITE32(open->op_why_no_deleg);
+               }
+               ADJUST_ARGS();
+               break;
        default:
                BUG();
        }
@@ -3008,7 +3020,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
        if (resp->xbuf->page_len)
                return nfserr_resource;
 
-       RESERVE_SPACE(8);  /* verifier */
+       RESERVE_SPACE(NFS4_VERIFIER_SIZE);
        savep = p;
 
        /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
@@ -3209,9 +3221,9 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
        __be32 *p;
 
        if (!nfserr) {
-               RESERVE_SPACE(8 + sizeof(nfs4_verifier));
+               RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE);
                WRITEMEM(&scd->se_clientid, 8);
-               WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
+               WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE);
                ADJUST_ARGS();
        }
        else if (nfserr == nfserr_clid_inuse) {
@@ -3232,7 +3244,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
                RESERVE_SPACE(16);
                WRITE32(write->wr_bytes_written);
                WRITE32(write->wr_how_written);
-               WRITEMEM(write->wr_verifier.data, 8);
+               WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE);
                ADJUST_ARGS();
        }
        return nfserr;
@@ -3391,30 +3403,17 @@ __be32
 nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
                          struct nfsd4_test_stateid *test_stateid)
 {
-       struct nfsd4_compoundargs *argp;
-       struct nfs4_client *cl = resp->cstate.session->se_client;
-       stateid_t si;
+       struct nfsd4_test_stateid_id *stateid, *next;
        __be32 *p;
-       int i;
-       int valid;
-
-       restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp);
-       argp = test_stateid->ts_saved_args;
 
-       RESERVE_SPACE(4);
+       RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids));
        *p++ = htonl(test_stateid->ts_num_ids);
-       resp->p = p;
 
-       nfs4_lock_state();
-       for (i = 0; i < test_stateid->ts_num_ids; i++) {
-               nfsd4_decode_stateid(argp, &si);
-               valid = nfs4_validate_stateid(cl, &si);
-               RESERVE_SPACE(4);
-               *p++ = htonl(valid);
-               resp->p = p;
+       list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
+               *p++ = htonl(stateid->ts_id_status);
        }
-       nfs4_unlock_state();
 
+       ADJUST_ARGS();
        return nfserr;
 }
 
@@ -3532,7 +3531,7 @@ int nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
        if (length > session->se_fchannel.maxresp_sz)
                return nfserr_rep_too_big;
 
-       if (slot->sl_cachethis == 1 &&
+       if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) &&
            length > session->se_fchannel.maxresp_cached)
                return nfserr_rep_too_big_to_cache;
 
@@ -3656,8 +3655,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
        if (nfsd4_has_session(cs)) {
                if (cs->status != nfserr_replay_cache) {
                        nfsd4_store_cache_entry(resp);
-                       dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
-                       cs->slot->sl_inuse = false;
+                       cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
                }
                /* Renew the clientid on success and on replay */
                release_session_client(cs->session);
index 64c24af8d7eaf40d5436aea2b2a6c44d588102e5..2c53be6d357957332478ed1d55d62c85cf9f26cc 100644 (file)
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/gss_api.h>
 #include <linux/sunrpc/gss_krb5_enctypes.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/module.h>
 
 #include "idmap.h"
 #include "nfsd.h"
 #include "cache.h"
 #include "fault_inject.h"
+#include "netns.h"
 
 /*
  *     We have a single directory with several nodes in it.
@@ -1124,14 +1126,26 @@ static int create_proc_exports_entry(void)
 }
 #endif
 
+int nfsd_net_id;
+static struct pernet_operations nfsd_net_ops = {
+       .id   = &nfsd_net_id,
+       .size = sizeof(struct nfsd_net),
+};
+
 static int __init init_nfsd(void)
 {
        int retval;
        printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
 
-       retval = nfsd4_init_slabs();
+       retval = register_cld_notifier();
        if (retval)
                return retval;
+       retval = register_pernet_subsys(&nfsd_net_ops);
+       if (retval < 0)
+               goto out_unregister_notifier;
+       retval = nfsd4_init_slabs();
+       if (retval)
+               goto out_unregister_pernet;
        nfs4_state_init();
        retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */
        if (retval)
@@ -1169,6 +1183,10 @@ out_free_stat:
        nfsd_fault_inject_cleanup();
 out_free_slabs:
        nfsd4_free_slabs();
+out_unregister_pernet:
+       unregister_pernet_subsys(&nfsd_net_ops);
+out_unregister_notifier:
+       unregister_cld_notifier();
        return retval;
 }
 
@@ -1184,6 +1202,8 @@ static void __exit exit_nfsd(void)
        nfsd4_free_slabs();
        nfsd_fault_inject_cleanup();
        unregister_filesystem(&nfsd_fs_type);
+       unregister_pernet_subsys(&nfsd_net_ops);
+       unregister_cld_notifier();
 }
 
 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
index 1d1e8589b4ce6ec02ad08dfbdd8848a051e67c2f..1671429ffa66fa1db509fbb212a09ad80d49efa8 100644 (file)
@@ -364,12 +364,17 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
        NFSD_WRITEABLE_ATTRS_WORD2
 
 extern int nfsd4_is_junction(struct dentry *dentry);
-#else
+extern int register_cld_notifier(void);
+extern void unregister_cld_notifier(void);
+#else /* CONFIG_NFSD_V4 */
 static inline int nfsd4_is_junction(struct dentry *dentry)
 {
        return 0;
 }
 
+#define register_cld_notifier() 0
+#define unregister_cld_notifier() do { } while(0)
+
 #endif /* CONFIG_NFSD_V4 */
 
 #endif /* LINUX_NFSD_NFSD_H */
index fce472f5f39e74f2fb9ab36bdf70019f573a73af..28dfad39f0c50a626384c4363955e2b9d7e3212f 100644 (file)
@@ -307,33 +307,37 @@ static void set_max_drc(void)
        dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem);
 }
 
-int nfsd_create_serv(void)
+static int nfsd_get_default_max_blksize(void)
 {
-       int err = 0;
+       struct sysinfo i;
+       unsigned long long target;
+       unsigned long ret;
+
+       si_meminfo(&i);
+       target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
+       /*
+        * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
+        * machines, but only uses 32K on 128M machines.  Bottom out at
+        * 8K on 32M and smaller.  Of course, this is only a default.
+        */
+       target >>= 12;
+
+       ret = NFSSVC_MAXBLKSIZE;
+       while (ret > target && ret >= 8*1024*2)
+               ret /= 2;
+       return ret;
+}
 
+int nfsd_create_serv(void)
+{
        WARN_ON(!mutex_is_locked(&nfsd_mutex));
        if (nfsd_serv) {
                svc_get(nfsd_serv);
                return 0;
        }
-       if (nfsd_max_blksize == 0) {
-               /* choose a suitable default */
-               struct sysinfo i;
-               si_meminfo(&i);
-               /* Aim for 1/4096 of memory per thread
-                * This gives 1MB on 4Gig machines
-                * But only uses 32K on 128M machines.
-                * Bottom out at 8K on 32M and smaller.
-                * Of course, this is only a default.
-                */
-               nfsd_max_blksize = NFSSVC_MAXBLKSIZE;
-               i.totalram <<= PAGE_SHIFT - 12;
-               while (nfsd_max_blksize > i.totalram &&
-                      nfsd_max_blksize >= 8*1024*2)
-                       nfsd_max_blksize /= 2;
-       }
+       if (nfsd_max_blksize == 0)
+               nfsd_max_blksize = nfsd_get_default_max_blksize();
        nfsd_reset_versions();
-
        nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
                                      nfsd_last_thread, nfsd, THIS_MODULE);
        if (nfsd_serv == NULL)
@@ -341,7 +345,7 @@ int nfsd_create_serv(void)
 
        set_max_drc();
        do_gettimeofday(&nfssvc_boot);          /* record boot time */
-       return err;
+       return 0;
 }
 
 int nfsd_nrpools(void)
index ffb5df1db94ff86558aff1340a6b07af2af29b79..89ab137d379a3f6756b5b5616083862e8f22d88f 100644 (file)
@@ -128,12 +128,14 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
                (NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE)
 
 struct nfsd4_slot {
-       bool    sl_inuse;
-       bool    sl_cachethis;
-       u16     sl_opcnt;
        u32     sl_seqid;
        __be32  sl_status;
        u32     sl_datalen;
+       u16     sl_opcnt;
+#define NFSD4_SLOT_INUSE       (1 << 0)
+#define NFSD4_SLOT_CACHETHIS   (1 << 1)
+#define NFSD4_SLOT_INITIALIZED (1 << 2)
+       u8      sl_flags;
        char    sl_data[];
 };
 
@@ -196,18 +198,7 @@ struct nfsd4_session {
        struct nfsd4_slot       *se_slots[];    /* forward channel slots */
 };
 
-static inline void
-nfsd4_put_session(struct nfsd4_session *ses)
-{
-       extern void free_session(struct kref *kref);
-       kref_put(&ses->se_ref, free_session);
-}
-
-static inline void
-nfsd4_get_session(struct nfsd4_session *ses)
-{
-       kref_get(&ses->se_ref);
-}
+extern void nfsd4_put_session(struct nfsd4_session *ses);
 
 /* formatted contents of nfs4_sessionid */
 struct nfsd4_sessionid {
@@ -245,14 +236,17 @@ struct nfs4_client {
        struct svc_cred         cl_cred;        /* setclientid principal */
        clientid_t              cl_clientid;    /* generated by server */
        nfs4_verifier           cl_confirm;     /* generated by server */
-       u32                     cl_firststate;  /* recovery dir creation */
        u32                     cl_minorversion;
 
        /* for v4.0 and v4.1 callbacks: */
        struct nfs4_cb_conn     cl_cb_conn;
-#define NFSD4_CLIENT_CB_UPDATE 1
-#define NFSD4_CLIENT_KILL      2
-       unsigned long           cl_cb_flags;
+#define NFSD4_CLIENT_CB_UPDATE         (0)
+#define NFSD4_CLIENT_CB_KILL           (1)
+#define NFSD4_CLIENT_STABLE            (2)     /* client on stable storage */
+#define NFSD4_CLIENT_RECLAIM_COMPLETE  (3)     /* reclaim_complete done */
+#define NFSD4_CLIENT_CB_FLAG_MASK      (1 << NFSD4_CLIENT_CB_UPDATE | \
+                                        1 << NFSD4_CLIENT_CB_KILL)
+       unsigned long           cl_flags;
        struct rpc_clnt         *cl_cb_client;
        u32                     cl_cb_ident;
 #define NFSD4_CB_UP            0
@@ -463,6 +457,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
 extern int nfs4_in_grace(void);
+extern void nfs4_release_reclaim(void);
+extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
 extern void nfs4_free_lockowner(struct nfs4_lockowner *);
@@ -477,16 +473,17 @@ extern void nfsd4_destroy_callback_queue(void);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
-extern void nfsd4_init_recdir(void);
-extern int nfsd4_recdir_load(void);
-extern void nfsd4_shutdown_recdir(void);
 extern int nfs4_client_to_reclaim(const char *name);
 extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
-extern void nfsd4_recdir_purge_old(void);
-extern void nfsd4_create_clid_dir(struct nfs4_client *clp);
-extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
 extern void release_session_client(struct nfsd4_session *);
 extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 
+/* nfs4recover operations */
+extern int nfsd4_client_tracking_init(struct net *net);
+extern void nfsd4_client_tracking_exit(struct net *net);
+extern void nfsd4_client_record_create(struct nfs4_client *clp);
+extern void nfsd4_client_record_remove(struct nfs4_client *clp);
+extern int nfsd4_client_record_check(struct nfs4_client *clp);
+extern void nfsd4_record_grace_done(struct net *net, time_t boot_time);
 #endif   /* NFSD4_STATE_H */
index e59f71d0cf73d355c5a71bffc1cfc7bf1eb11b02..296d671654d6a12fbb89567ea6b80cfd26a1829f 100644 (file)
@@ -737,12 +737,13 @@ static int nfsd_open_break_lease(struct inode *inode, int access)
 
 /*
  * Open an existing file or directory.
- * The access argument indicates the type of open (read/write/lock)
+ * The may_flags argument indicates the type of open (read/write/lock)
+ * and additional flags.
  * N.B. After this call fhp needs an fh_put
  */
 __be32
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
-                       int access, struct file **filp)
+                       int may_flags, struct file **filp)
 {
        struct dentry   *dentry;
        struct inode    *inode;
@@ -757,7 +758,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
         * and (hopefully) checked permission - so allow OWNER_OVERRIDE
         * in case a chmod has now revoked permission.
         */
-       err = fh_verify(rqstp, fhp, type, access | NFSD_MAY_OWNER_OVERRIDE);
+       err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE);
        if (err)
                goto out;
 
@@ -768,7 +769,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
         * or any access when mandatory locking enabled
         */
        err = nfserr_perm;
-       if (IS_APPEND(inode) && (access & NFSD_MAY_WRITE))
+       if (IS_APPEND(inode) && (may_flags & NFSD_MAY_WRITE))
                goto out;
        /*
         * We must ignore files (but only files) which might have mandatory
@@ -781,12 +782,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
        if (!inode->i_fop)
                goto out;
 
-       host_err = nfsd_open_break_lease(inode, access);
+       host_err = nfsd_open_break_lease(inode, may_flags);
        if (host_err) /* NOMEM or WOULDBLOCK */
                goto out_nfserr;
 
-       if (access & NFSD_MAY_WRITE) {
-               if (access & NFSD_MAY_READ)
+       if (may_flags & NFSD_MAY_WRITE) {
+               if (may_flags & NFSD_MAY_READ)
                        flags = O_RDWR|O_LARGEFILE;
                else
                        flags = O_WRONLY|O_LARGEFILE;
@@ -795,8 +796,15 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                            flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
-       else
-               host_err = ima_file_check(*filp, access);
+       else {
+               host_err = ima_file_check(*filp, may_flags);
+
+               if (may_flags & NFSD_MAY_64BIT_COOKIE)
+                       (*filp)->f_mode |= FMODE_64BITHASH;
+               else
+                       (*filp)->f_mode |= FMODE_32BITHASH;
+       }
+
 out_nfserr:
        err = nfserrno(host_err);
 out:
@@ -2021,8 +2029,13 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
        __be32          err;
        struct file     *file;
        loff_t          offset = *offsetp;
+       int             may_flags = NFSD_MAY_READ;
+
+       /* NFSv2 only supports 32 bit cookies */
+       if (rqstp->rq_vers > 2)
+               may_flags |= NFSD_MAY_64BIT_COOKIE;
 
-       err = nfsd_open(rqstp, fhp, S_IFDIR, NFSD_MAY_READ, &file);
+       err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
        if (err)
                goto out;
 
index 1dcd238e11a09c1051148f4ce27d3d06bb7da26a..ec0611b2b738468fbc261b35f2190048680e67dd 100644 (file)
@@ -27,6 +27,8 @@
 #define NFSD_MAY_BYPASS_GSS            0x400
 #define NFSD_MAY_READ_IF_EXEC          0x800
 
+#define NFSD_MAY_64BIT_COOKIE          0x1000 /* 64 bit readdir cookies for >= NFSv3 */
+
 #define NFSD_MAY_CREATE                (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
 #define NFSD_MAY_REMOVE                (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
 
index 2364747ee97db68d9d14600c1e849127f4ab9a71..1b3501598ab5dbb4609ba19e4f7c3322b29f70ba 100644 (file)
 #define NFSD4_MAX_TAGLEN       128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
 
+#define CURRENT_STATE_ID_FLAG (1<<0)
+#define SAVED_STATE_ID_FLAG (1<<1)
+
+#define SET_STATE_ID(c, f) ((c)->sid_flags |= (f))
+#define HAS_STATE_ID(c, f) ((c)->sid_flags & (f))
+#define CLEAR_STATE_ID(c, f) ((c)->sid_flags &= ~(f))
+
 struct nfsd4_compound_state {
        struct svc_fh           current_fh;
        struct svc_fh           save_fh;
@@ -54,6 +61,10 @@ struct nfsd4_compound_state {
        size_t                  iovlen;
        u32                     minorversion;
        u32                     status;
+       stateid_t       current_stateid;
+       stateid_t       save_stateid;
+       /* to indicate current and saved state id presents */
+       u32             sid_flags;
 };
 
 static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)
@@ -212,16 +223,19 @@ struct nfsd4_open {
        struct xdr_netobj op_fname;         /* request - everything but CLAIM_PREV */
        u32             op_delegate_type;   /* request - CLAIM_PREV only */
        stateid_t       op_delegate_stateid; /* request - response */
+       u32             op_why_no_deleg;    /* response - DELEG_NONE_EXT only */
        u32             op_create;          /* request */
        u32             op_createmode;      /* request */
        u32             op_bmval[3];        /* request */
        struct iattr    iattr;              /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
-       nfs4_verifier   verf;               /* EXCLUSIVE4 */
+       nfs4_verifier   op_verf __attribute__((aligned(32)));
+                                           /* EXCLUSIVE4 */
        clientid_t      op_clientid;        /* request */
        struct xdr_netobj op_owner;           /* request */
        u32             op_seqid;           /* request */
        u32             op_share_access;    /* request */
        u32             op_share_deny;      /* request */
+       u32             op_deleg_want;      /* request */
        stateid_t       op_stateid;         /* response */
        u32             op_recall;          /* recall */
        struct nfsd4_change_info  op_cinfo; /* response */
@@ -234,7 +248,6 @@ struct nfsd4_open {
        struct nfs4_acl *op_acl;
 };
 #define op_iattr       iattr
-#define op_verf                verf
 
 struct nfsd4_open_confirm {
        stateid_t       oc_req_stateid          /* request */;
@@ -245,8 +258,9 @@ struct nfsd4_open_confirm {
 struct nfsd4_open_downgrade {
        stateid_t       od_stateid;
        u32             od_seqid;
-       u32             od_share_access;
-       u32             od_share_deny;
+       u32             od_share_access;        /* request */
+       u32             od_deleg_want;          /* request */
+       u32             od_share_deny;          /* request */
 };
 
 
@@ -343,10 +357,15 @@ struct nfsd4_saved_compoundargs {
        struct page **pagelist;
 };
 
+struct nfsd4_test_stateid_id {
+       __be32                  ts_id_status;
+       stateid_t               ts_id_stateid;
+       struct list_head        ts_id_list;
+};
+
 struct nfsd4_test_stateid {
        __be32          ts_num_ids;
-       struct nfsd4_compoundargs *ts_saved_args;
-       struct nfsd4_saved_compoundargs ts_savedp;
+       struct list_head ts_stateid_list;
 };
 
 struct nfsd4_free_stateid {
@@ -503,7 +522,8 @@ static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp)
 
 static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
 {
-       return !resp->cstate.slot->sl_cachethis || nfsd4_is_solo_sequence(resp);
+       return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS)
+               || nfsd4_is_solo_sequence(resp);
 }
 
 #define NFS4_SVC_XDRSIZE               sizeof(struct nfsd4_compoundargs)
index 77becc04114908fae2a45f655ed22996264723ad..5720854156dbd61e28598da83a529294401eb119 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -836,7 +836,7 @@ EXPORT_SYMBOL(dentry_open);
 static void __put_unused_fd(struct files_struct *files, unsigned int fd)
 {
        struct fdtable *fdt = files_fdtable(files);
-       __FD_CLR(fd, fdt->open_fds);
+       __clear_open_fd(fd, fdt);
        if (fd < files->next_fd)
                files->next_fd = fd;
 }
@@ -1080,7 +1080,7 @@ SYSCALL_DEFINE1(close, unsigned int, fd)
        if (!filp)
                goto out_unlock;
        rcu_assign_pointer(fdt->fd[fd], NULL);
-       FD_CLR(fd, fdt->close_on_exec);
+       __clear_close_on_exec(fd, fdt);
        __put_unused_fd(files, fd);
        spin_unlock(&files->file_lock);
        retval = filp_close(filp, files);
index fbb53c249086bf074ef273b3c69378e5f1746157..f9bd395b3473f6f1ca5f0697679d7d469e9fdb7c 100644 (file)
@@ -550,7 +550,7 @@ int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
        seq_put_decimal_ull(m, ' ', shared);
        seq_put_decimal_ull(m, ' ', text);
        seq_put_decimal_ull(m, ' ', 0);
-       seq_put_decimal_ull(m, ' ', text);
+       seq_put_decimal_ull(m, ' ', data);
        seq_put_decimal_ull(m, ' ', 0);
        seq_putc(m, '\n');
 
index 3b42c1418f3118871d93275848f633217419129f..1c8b280146d7a0956dddd1f06e431f49671bd269 100644 (file)
@@ -1753,7 +1753,7 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
 
                        fdt = files_fdtable(files);
                        f_flags = file->f_flags & ~O_CLOEXEC;
-                       if (FD_ISSET(fd, fdt->close_on_exec))
+                       if (close_on_exec(fd, fdt))
                                f_flags |= O_CLOEXEC;
 
                        if (path) {
index 8461a7b82fdb5db92c058261abebb78812398f9c..205c92280838936d6402fa42792177748fd79ad8 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/mount.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "internal.h"
index 3551f1f839eb163801a22bfb1243211ee41b404f..0d9e23a39e495f0d6dd0a69d0f84aaa05faef9b5 100644 (file)
@@ -156,15 +156,15 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
        if (!ptrace_may_access(task, PTRACE_MODE_READ))
                goto out;
 
-       last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
-       for (entry = ns_entries; entry <= last; entry++) {
+       last = &ns_entries[ARRAY_SIZE(ns_entries)];
+       for (entry = ns_entries; entry < last; entry++) {
                if (strlen((*entry)->name) != len)
                        continue;
                if (!memcmp(dentry->d_name.name, (*entry)->name, len))
                        break;
        }
        error = ERR_PTR(-ENOENT);
-       if (entry > last)
+       if (entry == last)
                goto out;
 
        error = proc_ns_instantiate(dir, dentry, task, *entry);
index 9694cc2835115f18c5c6f9719d8ab9a332631901..2b9a7607cbd5496084ec386fcc2377752ab75107 100644 (file)
@@ -781,12 +781,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
        int err = 0;
        pagemap_entry_t pme = make_pme(PM_NOT_PRESENT);
 
-       if (pmd_trans_unstable(pmd))
-               return 0;
-
        /* find the first VMA at or above 'addr' */
        vma = find_vma(walk->mm, addr);
-       spin_lock(&walk->mm->page_table_lock);
        if (pmd_trans_huge_lock(pmd, vma) == 1) {
                for (; addr != end; addr += PAGE_SIZE) {
                        unsigned long offset;
@@ -802,6 +798,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                return err;
        }
 
+       if (pmd_trans_unstable(pmd))
+               return 0;
        for (; addr != end; addr += PAGE_SIZE) {
 
                /* check to see if we've left 'vma' behind
index cf9f4de00a957141d1d215c92190ebb1196f4035..b1a08573fe14277961aa3039ce0fb587d4f889cc 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 
 /* gets a struct reiserfs_journal_list * from a list head */
 #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
index 6fb8943d580bb178c35b900cff675e39c72ec259..17d33d09fc16f4843c72f9c7444dfdb3fb738952 100644 (file)
@@ -348,7 +348,7 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds)
        set = ~(~0UL << (n & (__NFDBITS-1)));
        n /= __NFDBITS;
        fdt = files_fdtable(current->files);
-       open_fds = fdt->open_fds->fds_bits+n;
+       open_fds = fdt->open_fds + n;
        max = 0;
        if (set) {
                set &= BITS(fds, n);
index ed0eb2a921f4bdb654bca99407b542db061b0054..fb50652e4e113f54a4447eb147fa56da59a8ba45 100644 (file)
@@ -83,7 +83,8 @@ static struct buffer_head *get_block_length(struct super_block *sb,
  * filesystem), otherwise the length is obtained from the first two bytes of
  * the metadata block.  A bit in the length field indicates if the block
  * is stored uncompressed in the filesystem (usually because compression
- * generated a larger block - this does occasionally happen with zlib).
+ * generated a larger block - this does occasionally happen with compression
+ * algorithms).
  */
 int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
                        int length, u64 *next_index, int srclength, int pages)
index 9dfe2ce0fb70f0b0caee3d14c9f0f3026bf5d3f4..b381305c9a47263ca34750b4e67172780047b9ca 100644 (file)
@@ -64,7 +64,7 @@ static int get_dir_index_using_offset(struct super_block *sb,
         * is offset by 3 because we invent "." and ".." entries which are
         * not actually stored in the directory.
         */
-       if (f_pos < 3)
+       if (f_pos <= 3)
                return f_pos;
        f_pos -= 3;
 
@@ -105,7 +105,7 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
        struct inode *inode = file->f_dentry->d_inode;
        struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
        u64 block = squashfs_i(inode)->start + msblk->directory_table;
-       int offset = squashfs_i(inode)->offset, length = 0, dir_count, size,
+       int offset = squashfs_i(inode)->offset, length, dir_count, size,
                                type, err;
        unsigned int inode_number;
        struct squashfs_dir_header dirh;
@@ -173,8 +173,7 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
 
                dir_count = le32_to_cpu(dirh.count) + 1;
 
-               /* dir_count should never be larger than 256 */
-               if (dir_count > 256)
+               if (dir_count > SQUASHFS_DIR_COUNT)
                        goto failed_read;
 
                while (dir_count--) {
index 0682b38d7e316beecc2c8ffe0a5c29b5e4997288..abcc58f3c15266dd24b9533b4b1103d3514a0c3e 100644 (file)
@@ -144,7 +144,7 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
        struct squashfs_dir_entry *dire;
        u64 block = squashfs_i(dir)->start + msblk->directory_table;
        int offset = squashfs_i(dir)->offset;
-       int err, length = 0, dir_count, size;
+       int err, length, dir_count, size;
 
        TRACE("Entered squashfs_lookup [%llx:%x]\n", block, offset);
 
@@ -177,8 +177,7 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
 
                dir_count = le32_to_cpu(dirh.count) + 1;
 
-               /* dir_count should never be larger than 256 */
-               if (dir_count > 256)
+               if (dir_count > SQUASHFS_DIR_COUNT)
                        goto data_error;
 
                while (dir_count--) {
index e8e14645de9a8107f6aa573e7392e7f95fae53bb..9e2349d07cb1c98334fd19ffbeb5441361f65edf 100644 (file)
 
 /* size of metadata (inode and directory) blocks */
 #define SQUASHFS_METADATA_SIZE         8192
-#define SQUASHFS_METADATA_LOG          13
-
-/* default size of data blocks */
-#define SQUASHFS_FILE_SIZE             131072
-#define SQUASHFS_FILE_LOG              17
 
 /* default size of block device I/O */
 #ifdef CONFIG_SQUASHFS_4K_DEVBLK_SIZE
 #define SQUASHFS_FILE_MAX_SIZE         1048576
 #define SQUASHFS_FILE_MAX_LOG          20
 
-/* Max number of uids and gids */
-#define SQUASHFS_IDS                   65536
-
 /* Max length of filename (not 255) */
 #define SQUASHFS_NAME_LEN              256
 
+/* Max value for directory header count*/
+#define SQUASHFS_DIR_COUNT             256
+
 #define SQUASHFS_INVALID_FRAG          (0xffffffffU)
 #define SQUASHFS_INVALID_XATTR         (0xffffffffU)
 #define SQUASHFS_INVALID_BLK           (-1LL)
 #define SQUASHFS_MKINODE(A, B)         ((long long)(((long long) (A)\
                                        << 16) + (B)))
 
-/* Translate between VFS mode and squashfs mode */
-#define SQUASHFS_MODE(A)               ((A) & 0xfff)
-
 /* fragment and fragment table defines */
 #define SQUASHFS_FRAGMENT_BYTES(A)     \
                                ((A) * sizeof(struct squashfs_fragment_entry))
 /* cached data constants for filesystem */
 #define SQUASHFS_CACHED_BLKS           8
 
-#define SQUASHFS_MAX_FILE_SIZE_LOG     64
-
-#define SQUASHFS_MAX_FILE_SIZE         (1LL << \
-                                       (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
-
 /* meta index cache */
 #define SQUASHFS_META_INDEXES  (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
 #define SQUASHFS_META_ENTRIES  127
index 970b1167e7cbda4e106abeb9e574da2726401906..29cd014ed3a17a776db73b4c1e492f44d78cba4e 100644 (file)
@@ -158,10 +158,15 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
+       /* Check block log for sanity */
        msblk->block_log = le16_to_cpu(sblk->block_log);
        if (msblk->block_log > SQUASHFS_FILE_MAX_LOG)
                goto failed_mount;
 
+       /* Check that block_size and block_log match */
+       if (msblk->block_size != (1 << msblk->block_log))
+               goto failed_mount;
+
        /* Check the root inode for sanity */
        root_inode = le64_to_cpu(sblk->root_inode);
        if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
index 9094e1d917beef62130a4aee162456f225dd0b02..7cdd3953d67e80733b252b6587aa47e72be46938 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index f636f6b460d0be3337870073793b467ed15c9429..ac8e279eccc668dcf1f6cd55c942569b9830e560 100644 (file)
@@ -73,7 +73,6 @@
 #include <stdarg.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index ce84ffd0264c86c77111145075c14fdc11b8a12f..0f0df2759b09213606a53c097d83a82a4a761c59 100644 (file)
@@ -35,6 +35,7 @@
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
+struct workqueue_struct *xfs_alloc_wq;
 
 #define XFS_ABSDIFF(a,b)       (((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
 
@@ -68,7 +69,7 @@ xfs_alloc_lookup_eq(
  * Lookup the first record greater than or equal to [bno, len]
  * in the btree given by cur.
  */
-STATIC int                             /* error */
+int                            /* error */
 xfs_alloc_lookup_ge(
        struct xfs_btree_cur    *cur,   /* btree cursor */
        xfs_agblock_t           bno,    /* starting block of extent */
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(
  * group or loop over the allocation groups to find the result.
  */
 int                            /* error */
-xfs_alloc_vextent(
+__xfs_alloc_vextent(
        xfs_alloc_arg_t *args)  /* allocation argument structure */
 {
        xfs_agblock_t   agsize; /* allocation group size */
@@ -2417,6 +2418,37 @@ error0:
        return error;
 }
 
+static void
+xfs_alloc_vextent_worker(
+       struct work_struct      *work)
+{
+       struct xfs_alloc_arg    *args = container_of(work,
+                                               struct xfs_alloc_arg, work);
+       unsigned long           pflags;
+
+       /* we are in a transaction context here */
+       current_set_flags_nested(&pflags, PF_FSTRANS);
+
+       args->result = __xfs_alloc_vextent(args);
+       complete(args->done);
+
+       current_restore_flags_nested(&pflags, PF_FSTRANS);
+}
+
+
+int                            /* error */
+xfs_alloc_vextent(
+       xfs_alloc_arg_t *args)  /* allocation argument structure */
+{
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       args->done = &done;
+       INIT_WORK(&args->work, xfs_alloc_vextent_worker);
+       queue_work(xfs_alloc_wq, &args->work);
+       wait_for_completion(&done);
+       return args->result;
+}
+
 /*
  * Free an extent.
  * Just break up the extent address and hand off to xfs_free_ag_extent
index 2f52b924be79f424b0a3115849af602f719a6b79..3a7e7d8f8dedd395872627abd23417435532dfb4 100644 (file)
@@ -25,6 +25,8 @@ struct xfs_perag;
 struct xfs_trans;
 struct xfs_busy_extent;
 
+extern struct workqueue_struct *xfs_alloc_wq;
+
 /*
  * Freespace allocation types.  Argument to xfs_alloc_[v]extent.
  */
@@ -119,6 +121,9 @@ typedef struct xfs_alloc_arg {
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
        xfs_fsblock_t   firstblock;     /* io first block allocated */
+       struct completion *done;
+       struct work_struct work;
+       int             result;
 } xfs_alloc_arg_t;
 
 /*
@@ -243,6 +248,13 @@ xfs_alloc_lookup_le(
        xfs_extlen_t            len,    /* length of extent */
        int                     *stat); /* success/failure */
 
+int                            /* error */
+xfs_alloc_lookup_ge(
+       struct xfs_btree_cur    *cur,   /* btree cursor */
+       xfs_agblock_t           bno,    /* starting block of extent */
+       xfs_extlen_t            len,    /* length of extent */
+       int                     *stat); /* success/failure */
+
 int                                    /* error */
 xfs_alloc_get_rec(
        struct xfs_btree_cur    *cur,   /* btree cursor */
index 08b9ac644c3140f6f6cc007f6f3eab05331ff35b..65d61b948eadbc287cdc7e61b2275436c9addb54 100644 (file)
@@ -853,6 +853,8 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
 {
        int newsize, forkoff, retval;
 
+       trace_xfs_attr_sf_addname(args);
+
        retval = xfs_attr_shortform_lookup(args);
        if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
                return(retval);
@@ -896,6 +898,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int retval, error, committed, forkoff;
 
+       trace_xfs_attr_leaf_addname(args);
+
        /*
         * Read the (only) block in the attribute list in.
         */
@@ -920,6 +924,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                        xfs_da_brelse(args->trans, bp);
                        return(retval);
                }
+
+               trace_xfs_attr_leaf_replace(args);
+
                args->op_flags |= XFS_DA_OP_RENAME;     /* an atomic rename */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
@@ -1090,6 +1097,8 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int error, committed, forkoff;
 
+       trace_xfs_attr_leaf_removename(args);
+
        /*
         * Remove the attribute.
         */
@@ -1223,6 +1232,8 @@ xfs_attr_node_addname(xfs_da_args_t *args)
        xfs_mount_t *mp;
        int committed, retval, error;
 
+       trace_xfs_attr_node_addname(args);
+
        /*
         * Fill in bucket of arguments/results/context to carry around.
         */
@@ -1249,6 +1260,9 @@ restart:
        } else if (retval == EEXIST) {
                if (args->flags & ATTR_CREATE)
                        goto out;
+
+               trace_xfs_attr_node_replace(args);
+
                args->op_flags |= XFS_DA_OP_RENAME;     /* atomic rename op */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
@@ -1480,6 +1494,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int retval, error, committed, forkoff;
 
+       trace_xfs_attr_node_removename(args);
+
        /*
         * Tie a string around our finger to remind us where we are.
         */
index d25eafd4d28de31d326078dbfdc21140c69b5acb..76d93dc953e15fea0a213955e1c8cd7223974d7b 100644 (file)
@@ -235,6 +235,8 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
        xfs_inode_t *dp;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_create(args);
+
        dp = args->dp;
        ASSERT(dp != NULL);
        ifp = dp->i_afp;
@@ -268,6 +270,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
        xfs_inode_t *dp;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_add(args);
+
        dp = args->dp;
        mp = dp->i_mount;
        dp->i_d.di_forkoff = forkoff;
@@ -337,6 +341,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
        xfs_mount_t *mp;
        xfs_inode_t *dp;
 
+       trace_xfs_attr_sf_remove(args);
+
        dp = args->dp;
        mp = dp->i_mount;
        base = sizeof(xfs_attr_sf_hdr_t);
@@ -405,6 +411,8 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args)
        int i;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_lookup(args);
+
        ifp = args->dp->i_afp;
        ASSERT(ifp->if_flags & XFS_IFINLINE);
        sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
@@ -476,6 +484,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_to_leaf(args);
+
        dp = args->dp;
        ifp = dp->i_afp;
        sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
@@ -775,6 +785,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
        char *tmpbuffer;
        int error, i;
 
+       trace_xfs_attr_leaf_to_sf(args);
+
        dp = args->dp;
        tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
        ASSERT(tmpbuffer != NULL);
@@ -848,6 +860,8 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
        xfs_dablk_t blkno;
        int error;
 
+       trace_xfs_attr_leaf_to_node(args);
+
        dp = args->dp;
        bp1 = bp2 = NULL;
        error = xfs_da_grow_inode(args, &blkno);
@@ -911,6 +925,8 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
        xfs_dabuf_t *bp;
        int error;
 
+       trace_xfs_attr_leaf_create(args);
+
        dp = args->dp;
        ASSERT(dp != NULL);
        error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp,
@@ -948,6 +964,8 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        xfs_dablk_t blkno;
        int error;
 
+       trace_xfs_attr_leaf_split(state->args);
+
        /*
         * Allocate space for a new leaf node.
         */
@@ -977,10 +995,13 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
         *
         * Insert the "new" entry in the correct block.
         */
-       if (state->inleaf)
+       if (state->inleaf) {
+               trace_xfs_attr_leaf_add_old(state->args);
                error = xfs_attr_leaf_add(oldblk->bp, state->args);
-       else
+       } else {
+               trace_xfs_attr_leaf_add_new(state->args);
                error = xfs_attr_leaf_add(newblk->bp, state->args);
+       }
 
        /*
         * Update last hashval in each block since we added the name.
@@ -1001,6 +1022,8 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
        xfs_attr_leaf_map_t *map;
        int tablesize, entsize, sum, tmp, i;
 
+       trace_xfs_attr_leaf_add(args);
+
        leaf = bp->data;
        ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT((args->index >= 0)
@@ -1128,8 +1151,6 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
               (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval)));
 
        /*
-        * Copy the attribute name and value into the new space.
-        *
         * For "remote" attribute values, simply note that we need to
         * allocate space for the "remote" value.  We can't actually
         * allocate the extents in this transaction, and we can't decide
@@ -1265,6 +1286,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        args = state->args;
 
+       trace_xfs_attr_leaf_rebalance(args);
+
        /*
         * Check ordering of blocks, reverse if it makes things simpler.
         *
@@ -1810,6 +1833,8 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
        xfs_mount_t *mp;
        char *tmpbuffer;
 
+       trace_xfs_attr_leaf_unbalance(state->args);
+
        /*
         * Set up environment.
         */
@@ -1919,6 +1944,8 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
        int probe, span;
        xfs_dahash_t hashval;
 
+       trace_xfs_attr_leaf_lookup(args);
+
        leaf = bp->data;
        ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT(be16_to_cpu(leaf->hdr.count)
@@ -2445,6 +2472,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
        char *name;
 #endif /* DEBUG */
 
+       trace_xfs_attr_leaf_clearflag(args);
        /*
         * Set up the operation.
         */
@@ -2509,6 +2537,8 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int error;
 
+       trace_xfs_attr_leaf_setflag(args);
+
        /*
         * Set up the operation.
         */
@@ -2565,6 +2595,8 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
        char *name1, *name2;
 #endif /* DEBUG */
 
+       trace_xfs_attr_leaf_flipflags(args);
+
        /*
         * Read the block containing the "old" attr
         */
index 3548c6f75593d1d1f3acd949ea2677f072f19e2d..85e7e327bcd87fdbc7efcb1d707612bd11369196 100644 (file)
@@ -5124,6 +5124,15 @@ xfs_bunmapi(
                cur->bc_private.b.flags = 0;
        } else
                cur = NULL;
+
+       if (isrt) {
+               /*
+                * Synchronize by locking the bitmap inode.
+                */
+               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+       }
+
        extno = 0;
        while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
               (nexts == 0 || extno < nexts)) {
index df7ffb0affe73f795ab4eee512cf7035e2c0b6f7..5bf3be45f54352b628df03936eb719fd7397064e 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
index 77c74257c2a3b7e631f9ebfa6e25f6b1f3bcf46d..7f1a6f5b05a6785895f93c5a1c08508c1a99e10f 100644 (file)
@@ -108,6 +108,8 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
        int error;
        xfs_trans_t *tp;
 
+       trace_xfs_da_node_create(args);
+
        tp = args->trans;
        error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
        if (error)
@@ -140,6 +142,8 @@ xfs_da_split(xfs_da_state_t *state)
        xfs_dabuf_t *bp;
        int max, action, error, i;
 
+       trace_xfs_da_split(state->args);
+
        /*
         * Walk back up the tree splitting/inserting/adjusting as necessary.
         * If we need to insert and there isn't room, split the node, then
@@ -178,10 +182,12 @@ xfs_da_split(xfs_da_state_t *state)
                        state->extravalid = 1;
                        if (state->inleaf) {
                                state->extraafter = 0;  /* before newblk */
+                               trace_xfs_attr_leaf_split_before(state->args);
                                error = xfs_attr_leaf_split(state, oldblk,
                                                            &state->extrablk);
                        } else {
                                state->extraafter = 1;  /* after newblk */
+                               trace_xfs_attr_leaf_split_after(state->args);
                                error = xfs_attr_leaf_split(state, newblk,
                                                            &state->extrablk);
                        }
@@ -300,6 +306,8 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        xfs_mount_t *mp;
        xfs_dir2_leaf_t *leaf;
 
+       trace_xfs_da_root_split(state->args);
+
        /*
         * Copy the existing (incorrect) block from the root node position
         * to a free space somewhere.
@@ -380,6 +388,8 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        int newcount, error;
        int useextra;
 
+       trace_xfs_da_node_split(state->args);
+
        node = oldblk->bp->data;
        ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 
@@ -466,6 +476,8 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        int count, tmp;
        xfs_trans_t *tp;
 
+       trace_xfs_da_node_rebalance(state->args);
+
        node1 = blk1->bp->data;
        node2 = blk2->bp->data;
        /*
@@ -574,6 +586,8 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        xfs_da_node_entry_t *btree;
        int tmp;
 
+       trace_xfs_da_node_add(state->args);
+
        node = oldblk->bp->data;
        ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
        ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
@@ -619,6 +633,8 @@ xfs_da_join(xfs_da_state_t *state)
        xfs_da_state_blk_t *drop_blk, *save_blk;
        int action, error;
 
+       trace_xfs_da_join(state->args);
+
        action = 0;
        drop_blk = &state->path.blk[ state->path.active-1 ];
        save_blk = &state->altpath.blk[ state->path.active-1 ];
@@ -723,6 +739,8 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
        xfs_dabuf_t *bp;
        int error;
 
+       trace_xfs_da_root_join(state->args);
+
        args = state->args;
        ASSERT(args != NULL);
        ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
@@ -941,6 +959,8 @@ xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk)
        xfs_da_node_entry_t *btree;
        int tmp;
 
+       trace_xfs_da_node_remove(state->args);
+
        node = drop_blk->bp->data;
        ASSERT(drop_blk->index < be16_to_cpu(node->hdr.count));
        ASSERT(drop_blk->index >= 0);
@@ -984,6 +1004,8 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
        int tmp;
        xfs_trans_t *tp;
 
+       trace_xfs_da_node_unbalance(state->args);
+
        drop_node = drop_blk->bp->data;
        save_node = save_blk->bp->data;
        ASSERT(drop_node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
@@ -1230,6 +1252,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
                /*
                 * Link new block in before existing block.
                 */
+               trace_xfs_da_link_before(args);
                new_info->forw = cpu_to_be32(old_blk->blkno);
                new_info->back = old_info->back;
                if (old_info->back) {
@@ -1251,6 +1274,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
                /*
                 * Link new block in after existing block.
                 */
+               trace_xfs_da_link_after(args);
                new_info->forw = old_info->forw;
                new_info->back = cpu_to_be32(old_blk->blkno);
                if (old_info->forw) {
@@ -1348,6 +1372,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
         * Unlink the leaf block from the doubly linked chain of leaves.
         */
        if (be32_to_cpu(save_info->back) == drop_blk->blkno) {
+               trace_xfs_da_unlink_back(args);
                save_info->back = drop_info->back;
                if (drop_info->back) {
                        error = xfs_da_read_buf(args->trans, args->dp,
@@ -1365,6 +1390,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
                        xfs_da_buf_done(bp);
                }
        } else {
+               trace_xfs_da_unlink_forward(args);
                save_info->forw = drop_info->forw;
                if (drop_info->forw) {
                        error = xfs_da_read_buf(args->trans, args->dp,
@@ -1652,6 +1678,8 @@ xfs_da_grow_inode(
        int                     count;
        int                     error;
 
+       trace_xfs_da_grow_inode(args);
+
        if (args->whichfork == XFS_DATA_FORK) {
                bno = args->dp->i_mount->m_dirleafblk;
                count = args->dp->i_mount->m_dirblkfsbs;
@@ -1690,6 +1718,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
        xfs_dir2_leaf_t *dead_leaf2;
        xfs_dahash_t dead_hash;
 
+       trace_xfs_da_swap_lastblock(args);
+
        dead_buf = *dead_bufp;
        dead_blkno = *dead_blknop;
        tp = args->trans;
@@ -1878,6 +1908,8 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
        xfs_trans_t *tp;
        xfs_mount_t *mp;
 
+       trace_xfs_da_shrink_inode(args);
+
        dp = args->dp;
        w = args->whichfork;
        tp = args->trans;
index 286a051f12cfd779f553f209452cd2539d042de6..1ad3a4b8ca408a2f60c2eef69a101907342786f9 100644 (file)
@@ -37,9 +37,9 @@ STATIC int
 xfs_trim_extents(
        struct xfs_mount        *mp,
        xfs_agnumber_t          agno,
-       xfs_fsblock_t           start,
-       xfs_fsblock_t           end,
-       xfs_fsblock_t           minlen,
+       xfs_daddr_t             start,
+       xfs_daddr_t             end,
+       xfs_daddr_t             minlen,
        __uint64_t              *blocks_trimmed)
 {
        struct block_device     *bdev = mp->m_ddev_targp->bt_bdev;
@@ -67,7 +67,7 @@ xfs_trim_extents(
        /*
         * Look up the longest btree in the AGF and start with it.
         */
-       error = xfs_alloc_lookup_le(cur, 0,
+       error = xfs_alloc_lookup_ge(cur, 0,
                            be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest), &i);
        if (error)
                goto out_del_cursor;
@@ -77,8 +77,10 @@ xfs_trim_extents(
         * enough to be worth discarding.
         */
        while (i) {
-               xfs_agblock_t fbno;
-               xfs_extlen_t flen;
+               xfs_agblock_t   fbno;
+               xfs_extlen_t    flen;
+               xfs_daddr_t     dbno;
+               xfs_extlen_t    dlen;
 
                error = xfs_alloc_get_rec(cur, &fbno, &flen, &i);
                if (error)
@@ -86,10 +88,18 @@ xfs_trim_extents(
                XFS_WANT_CORRUPTED_GOTO(i == 1, out_del_cursor);
                ASSERT(flen <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest));
 
+               /*
+                * use daddr format for all range/len calculations as that is
+                * the format the range/len variables are supplied in by
+                * userspace.
+                */
+               dbno = XFS_AGB_TO_DADDR(mp, agno, fbno);
+               dlen = XFS_FSB_TO_BB(mp, flen);
+
                /*
                 * Too small?  Give up.
                 */
-               if (flen < minlen) {
+               if (dlen < minlen) {
                        trace_xfs_discard_toosmall(mp, agno, fbno, flen);
                        goto out_del_cursor;
                }
@@ -99,8 +109,7 @@ xfs_trim_extents(
                 * supposed to discard skip it.  Do not bother to trim
                 * down partially overlapping ranges for now.
                 */
-               if (XFS_AGB_TO_FSB(mp, agno, fbno) + flen < start ||
-                   XFS_AGB_TO_FSB(mp, agno, fbno) > end) {
+               if (dbno + dlen < start || dbno > end) {
                        trace_xfs_discard_exclude(mp, agno, fbno, flen);
                        goto next_extent;
                }
@@ -115,10 +124,7 @@ xfs_trim_extents(
                }
 
                trace_xfs_discard_extent(mp, agno, fbno, flen);
-               error = -blkdev_issue_discard(bdev,
-                               XFS_AGB_TO_DADDR(mp, agno, fbno),
-                               XFS_FSB_TO_BB(mp, flen),
-                               GFP_NOFS, 0);
+               error = -blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS, 0);
                if (error)
                        goto out_del_cursor;
                *blocks_trimmed += flen;
@@ -137,6 +143,15 @@ out_put_perag:
        return error;
 }
 
+/*
+ * trim a range of the filesystem.
+ *
+ * Note: the parameters passed from userspace are byte ranges into the
+ * filesystem which does not match to the format we use for filesystem block
+ * addressing. FSB addressing is sparse (AGNO|AGBNO), while the incoming format
+ * is a linear address range. Hence we need to use DADDR based conversions and
+ * comparisons for determining the correct offset and regions to trim.
+ */
 int
 xfs_ioc_trim(
        struct xfs_mount                *mp,
@@ -145,7 +160,7 @@ xfs_ioc_trim(
        struct request_queue    *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
        unsigned int            granularity = q->limits.discard_granularity;
        struct fstrim_range     range;
-       xfs_fsblock_t           start, end, minlen;
+       xfs_daddr_t             start, end, minlen;
        xfs_agnumber_t          start_agno, end_agno, agno;
        __uint64_t              blocks_trimmed = 0;
        int                     error, last_error = 0;
@@ -159,22 +174,22 @@ xfs_ioc_trim(
 
        /*
         * Truncating down the len isn't actually quite correct, but using
-        * XFS_B_TO_FSB would mean we trivially get overflows for values
+        * BBTOB would mean we trivially get overflows for values
         * of ULLONG_MAX or slightly lower.  And ULLONG_MAX is the default
         * used by the fstrim application.  In the end it really doesn't
         * matter as trimming blocks is an advisory interface.
         */
-       start = XFS_B_TO_FSBT(mp, range.start);
-       end = start + XFS_B_TO_FSBT(mp, range.len) - 1;
-       minlen = XFS_B_TO_FSB(mp, max_t(u64, granularity, range.minlen));
+       start = BTOBB(range.start);
+       end = start + BTOBBT(range.len) - 1;
+       minlen = BTOBB(max_t(u64, granularity, range.minlen));
 
-       if (start >= mp->m_sb.sb_dblocks)
+       if (XFS_BB_TO_FSB(mp, start) >= mp->m_sb.sb_dblocks)
                return -XFS_ERROR(EINVAL);
-       if (end > mp->m_sb.sb_dblocks - 1)
-               end = mp->m_sb.sb_dblocks - 1;
+       if (end > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) - 1)
+               end = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)- 1;
 
-       start_agno = XFS_FSB_TO_AGNO(mp, start);
-       end_agno = XFS_FSB_TO_AGNO(mp, end);
+       start_agno = xfs_daddr_to_agno(mp, start);
+       end_agno = xfs_daddr_to_agno(mp, end);
 
        for (agno = start_agno; agno <= end_agno; agno++) {
                error = -xfs_trim_extents(mp, agno, start, end, minlen,
index 4be16a0cbe5aee7caf7854c720e371b1e9d851c2..1155208fa830f2953ca0e1019f59b1b9379af7e2 100644 (file)
@@ -1065,7 +1065,7 @@ out:
        return -ENOMEM;
 }
 
-void __exit
+void
 xfs_qm_exit(void)
 {
        kmem_zone_destroy(xfs_qm_dqtrxzone);
index a98cb4524e6cbc8d0c5064813014c36963bc03e0..bcc6c249b2c76016ad26efd15523073c569273a9 100644 (file)
@@ -289,7 +289,7 @@ xfs_iget_cache_hit(
        if (lock_flags != 0)
                xfs_ilock(ip, lock_flags);
 
-       xfs_iflags_clear(ip, XFS_ISTALE);
+       xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
        XFS_STATS_INC(xs_ig_found);
 
        return 0;
@@ -314,6 +314,7 @@ xfs_iget_cache_miss(
        struct xfs_inode        *ip;
        int                     error;
        xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
+       int                     iflags;
 
        ip = xfs_inode_alloc(mp, ino);
        if (!ip)
@@ -358,8 +359,11 @@ xfs_iget_cache_miss(
         * memory barrier that ensures this detection works correctly at lookup
         * time.
         */
+       iflags = XFS_INEW;
+       if (flags & XFS_IGET_DONTCACHE)
+               iflags |= XFS_IDONTCACHE;
        ip->i_udquot = ip->i_gdquot = NULL;
-       xfs_iflags_set(ip, XFS_INEW);
+       xfs_iflags_set(ip, iflags);
 
        /* insert the new inode */
        spin_lock(&pag->pag_ici_lock);
index f123dbe6d42a0e4203f1db43980dd29e097311f9..7fee3387e1c8cd6d8ec619f074bd00905a3cbba1 100644 (file)
@@ -387,10 +387,11 @@ xfs_set_projid(struct xfs_inode *ip,
 #define XFS_IFLOCK             (1 << __XFS_IFLOCK_BIT)
 #define __XFS_IPINNED_BIT      8        /* wakeup key for zero pin count */
 #define XFS_IPINNED            (1 << __XFS_IPINNED_BIT)
+#define XFS_IDONTCACHE         (1 << 9) /* don't cache the inode long term */
 
 /*
  * Per-lifetime flags need to be reset when re-using a reclaimable inode during
- * inode lookup. Thi prevents unintended behaviour on the new inode from
+ * inode lookup. This prevents unintended behaviour on the new inode from
  * ocurring.
  */
 #define XFS_IRECLAIM_RESET_FLAGS       \
@@ -553,6 +554,7 @@ do { \
  */
 #define XFS_IGET_CREATE                0x1
 #define XFS_IGET_UNTRUSTED     0x2
+#define XFS_IGET_DONTCACHE     0x4
 
 int            xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
                            xfs_ino_t, struct xfs_dinode **,
index f588320dc4b9070a6d2c65244a9a7ed9ac1cc462..91f8ff547ab3771f3df70e631aaf0804256f8eba 100644 (file)
@@ -209,6 +209,7 @@ xfs_open_by_handle(
        struct file             *filp;
        struct inode            *inode;
        struct dentry           *dentry;
+       fmode_t                 fmode;
 
        if (!capable(CAP_SYS_ADMIN))
                return -XFS_ERROR(EPERM);
@@ -228,26 +229,21 @@ xfs_open_by_handle(
        hreq->oflags |= O_LARGEFILE;
 #endif
 
-       /* Put open permission in namei format. */
        permflag = hreq->oflags;
-       if ((permflag+1) & O_ACCMODE)
-               permflag++;
-       if (permflag & O_TRUNC)
-               permflag |= 2;
-
+       fmode = OPEN_FMODE(permflag);
        if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
-           (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
+           (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
                error = -XFS_ERROR(EPERM);
                goto out_dput;
        }
 
-       if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
+       if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
                error = -XFS_ERROR(EACCES);
                goto out_dput;
        }
 
        /* Can't write directories. */
-       if (S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
+       if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
                error = -XFS_ERROR(EISDIR);
                goto out_dput;
        }
index 9720c54bbed0dd4a37e9ebc6bbb33bf9ee8fdbf7..acc2bf264dab7341058ef23c15ed8c1417183d1e 100644 (file)
@@ -75,7 +75,8 @@ xfs_bulkstat_one_int(
                return XFS_ERROR(ENOMEM);
 
        error = xfs_iget(mp, NULL, ino,
-                        XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip);
+                        (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED),
+                        XFS_ILOCK_SHARED, &ip);
        if (error) {
                *stat = BULKSTAT_RV_NOTHING;
                goto out_free;
index 98a9cb5ffd1700995e8118e71524ba6d12e12fa2..6db1fef38bffdbdf8420fc5855b67698a4bddb55 100644 (file)
@@ -726,8 +726,9 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                                .lv_iovecp = &reg,
                        };
 
-                       /* remove inited flag */
+                       /* remove inited flag, and account for space used */
                        tic->t_flags = 0;
+                       tic->t_curr_res -= sizeof(magic);
                        error = xlog_write(log, &vec, tic, &lsn,
                                           NULL, XLOG_UNMOUNT_TRANS);
                        /*
index 7c75c7374d5a4acfdc1e83e139db95294d35fd58..8ecad5bad66cc5f7cfa1bad68fd30b220c5d30d3 100644 (file)
@@ -3161,37 +3161,26 @@ xlog_recover_process_iunlinks(
                         */
                        continue;
                }
+               /*
+                * Unlock the buffer so that it can be acquired in the normal
+                * course of the transaction to truncate and free each inode.
+                * Because we are not racing with anyone else here for the AGI
+                * buffer, we don't even need to hold it locked to read the
+                * initial unlinked bucket entries out of the buffer. We keep
+                * buffer reference though, so that it stays pinned in memory
+                * while we need the buffer.
+                */
                agi = XFS_BUF_TO_AGI(agibp);
+               xfs_buf_unlock(agibp);
 
                for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
                        agino = be32_to_cpu(agi->agi_unlinked[bucket]);
                        while (agino != NULLAGINO) {
-                               /*
-                                * Release the agi buffer so that it can
-                                * be acquired in the normal course of the
-                                * transaction to truncate and free the inode.
-                                */
-                               xfs_buf_relse(agibp);
-
                                agino = xlog_recover_process_one_iunlink(mp,
                                                        agno, agino, bucket);
-
-                               /*
-                                * Reacquire the agibuffer and continue around
-                                * the loop. This should never fail as we know
-                                * the buffer was good earlier on.
-                                */
-                               error = xfs_read_agi(mp, NULL, agno, &agibp);
-                               ASSERT(error == 0);
-                               agi = XFS_BUF_TO_AGI(agibp);
                        }
                }
-
-               /*
-                * Release the buffer for the current agi so we can
-                * go on to the next one.
-                */
-               xfs_buf_relse(agibp);
+               xfs_buf_rele(agibp);
        }
 
        mp->m_dmevmask = mp_dmevmask;
index 87323f1ded6466482f40b019d81fbbcc4905e400..ca4f31534a0a5f9e3fa113824bf41a170ac1ad37 100644 (file)
@@ -183,6 +183,7 @@ error_cancel:
                oblocks = map.br_startoff + map.br_blockcount;
        }
        return 0;
+
 error:
        return error;
 }
@@ -2139,11 +2140,9 @@ xfs_rtfree_extent(
        xfs_buf_t       *sumbp;         /* summary file block buffer */
 
        mp = tp->t_mountp;
-       /*
-        * Synchronize by locking the bitmap inode.
-        */
-       xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
+       ASSERT(mp->m_rbmip->i_itemp != NULL);
+       ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
 
 #if defined(__KERNEL__) && defined(DEBUG)
        /*
index 912442cf0f82c3a285fa7d49cab22baa03553f53..dab9a5f6dfd68345646849f6ca391fa3849839bb 100644 (file)
@@ -950,6 +950,22 @@ xfs_fs_evict_inode(
        xfs_inactive(ip);
 }
 
+/*
+ * We do an unlocked check for XFS_IDONTCACHE here because we are already
+ * serialised against cache hits here via the inode->i_lock and igrab() in
+ * xfs_iget_cache_hit(). Hence a lookup that might clear this flag will not be
+ * racing with us, and it avoids needing to grab a spinlock here for every inode
+ * we drop the final reference on.
+ */
+STATIC int
+xfs_fs_drop_inode(
+       struct inode            *inode)
+{
+       struct xfs_inode        *ip = XFS_I(inode);
+
+       return generic_drop_inode(inode) || (ip->i_flags & XFS_IDONTCACHE);
+}
+
 STATIC void
 xfs_free_fsname(
        struct xfs_mount        *mp)
@@ -1433,6 +1449,7 @@ static const struct super_operations xfs_super_operations = {
        .destroy_inode          = xfs_fs_destroy_inode,
        .dirty_inode            = xfs_fs_dirty_inode,
        .evict_inode            = xfs_fs_evict_inode,
+       .drop_inode             = xfs_fs_drop_inode,
        .put_super              = xfs_fs_put_super,
        .sync_fs                = xfs_fs_sync_fs,
        .freeze_fs              = xfs_fs_freeze,
@@ -1606,12 +1623,28 @@ xfs_init_workqueues(void)
        xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0);
        if (!xfs_syncd_wq)
                return -ENOMEM;
+
+       /*
+        * The allocation workqueue can be used in memory reclaim situations
+        * (writepage path), and parallelism is only limited by the number of
+        * AGs in all the filesystems mounted. Hence use the default large
+        * max_active value for this workqueue.
+        */
+       xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0);
+       if (!xfs_alloc_wq)
+               goto out_destroy_syncd;
+
        return 0;
+
+out_destroy_syncd:
+       destroy_workqueue(xfs_syncd_wq);
+       return -ENOMEM;
 }
 
 STATIC void
 xfs_destroy_workqueues(void)
 {
+       destroy_workqueue(xfs_alloc_wq);
        destroy_workqueue(xfs_syncd_wq);
 }
 
index 75eb54af4d581e7f4cc9270f0abb1c72238195ac..06838c42b2a0ef966b85538a3b644d8b09a919db 100644 (file)
@@ -627,16 +627,19 @@ DECLARE_EVENT_CLASS(xfs_namespace_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_ino_t, dp_ino)
+               __field(int, namelen)
                __dynamic_array(char, name, name->len)
        ),
        TP_fast_assign(
                __entry->dev = VFS_I(dp)->i_sb->s_dev;
                __entry->dp_ino = dp->i_ino;
+               __entry->namelen = name->len;
                memcpy(__get_str(name), name->name, name->len);
        ),
-       TP_printk("dev %d:%d dp ino 0x%llx name %s",
+       TP_printk("dev %d:%d dp ino 0x%llx name %.*s",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->dp_ino,
+                 __entry->namelen,
                  __get_str(name))
 )
 
@@ -658,6 +661,8 @@ TRACE_EVENT(xfs_rename,
                __field(dev_t, dev)
                __field(xfs_ino_t, src_dp_ino)
                __field(xfs_ino_t, target_dp_ino)
+               __field(int, src_namelen)
+               __field(int, target_namelen)
                __dynamic_array(char, src_name, src_name->len)
                __dynamic_array(char, target_name, target_name->len)
        ),
@@ -665,15 +670,20 @@ TRACE_EVENT(xfs_rename,
                __entry->dev = VFS_I(src_dp)->i_sb->s_dev;
                __entry->src_dp_ino = src_dp->i_ino;
                __entry->target_dp_ino = target_dp->i_ino;
+               __entry->src_namelen = src_name->len;
+               __entry->target_namelen = target_name->len;
                memcpy(__get_str(src_name), src_name->name, src_name->len);
-               memcpy(__get_str(target_name), target_name->name, target_name->len);
+               memcpy(__get_str(target_name), target_name->name,
+                       target_name->len);
        ),
        TP_printk("dev %d:%d src dp ino 0x%llx target dp ino 0x%llx"
-                 " src name %s target name %s",
+                 " src name %.*s target name %.*s",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->src_dp_ino,
                  __entry->target_dp_ino,
+                 __entry->src_namelen,
                  __get_str(src_name),
+                 __entry->target_namelen,
                  __get_str(target_name))
 )
 
@@ -1408,7 +1418,7 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed);
 
-DECLARE_EVENT_CLASS(xfs_dir2_class,
+DECLARE_EVENT_CLASS(xfs_da_class,
        TP_PROTO(struct xfs_da_args *args),
        TP_ARGS(args),
        TP_STRUCT__entry(
@@ -1443,7 +1453,7 @@ DECLARE_EVENT_CLASS(xfs_dir2_class,
 )
 
 #define DEFINE_DIR2_EVENT(name) \
-DEFINE_EVENT(xfs_dir2_class, name, \
+DEFINE_EVENT(xfs_da_class, name, \
        TP_PROTO(struct xfs_da_args *args), \
        TP_ARGS(args))
 DEFINE_DIR2_EVENT(xfs_dir2_sf_addname);
@@ -1472,6 +1482,64 @@ DEFINE_DIR2_EVENT(xfs_dir2_node_replace);
 DEFINE_DIR2_EVENT(xfs_dir2_node_removename);
 DEFINE_DIR2_EVENT(xfs_dir2_node_to_leaf);
 
+#define DEFINE_ATTR_EVENT(name) \
+DEFINE_EVENT(xfs_da_class, name, \
+       TP_PROTO(struct xfs_da_args *args), \
+       TP_ARGS(args))
+DEFINE_ATTR_EVENT(xfs_attr_sf_add);
+DEFINE_ATTR_EVENT(xfs_attr_sf_addname);
+DEFINE_ATTR_EVENT(xfs_attr_sf_create);
+DEFINE_ATTR_EVENT(xfs_attr_sf_lookup);
+DEFINE_ATTR_EVENT(xfs_attr_sf_remove);
+DEFINE_ATTR_EVENT(xfs_attr_sf_removename);
+DEFINE_ATTR_EVENT(xfs_attr_sf_to_leaf);
+
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add_old);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add_new);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_addname);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_create);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_lookup);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_replace);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_removename);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_split);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_split_before);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_split_after);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_clearflag);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_setflag);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_flipflags);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_to_sf);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_to_node);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_rebalance);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_unbalance);
+
+DEFINE_ATTR_EVENT(xfs_attr_node_addname);
+DEFINE_ATTR_EVENT(xfs_attr_node_lookup);
+DEFINE_ATTR_EVENT(xfs_attr_node_replace);
+DEFINE_ATTR_EVENT(xfs_attr_node_removename);
+
+#define DEFINE_DA_EVENT(name) \
+DEFINE_EVENT(xfs_da_class, name, \
+       TP_PROTO(struct xfs_da_args *args), \
+       TP_ARGS(args))
+DEFINE_DA_EVENT(xfs_da_split);
+DEFINE_DA_EVENT(xfs_da_join);
+DEFINE_DA_EVENT(xfs_da_link_before);
+DEFINE_DA_EVENT(xfs_da_link_after);
+DEFINE_DA_EVENT(xfs_da_unlink_back);
+DEFINE_DA_EVENT(xfs_da_unlink_forward);
+DEFINE_DA_EVENT(xfs_da_root_split);
+DEFINE_DA_EVENT(xfs_da_root_join);
+DEFINE_DA_EVENT(xfs_da_node_add);
+DEFINE_DA_EVENT(xfs_da_node_create);
+DEFINE_DA_EVENT(xfs_da_node_split);
+DEFINE_DA_EVENT(xfs_da_node_remove);
+DEFINE_DA_EVENT(xfs_da_node_rebalance);
+DEFINE_DA_EVENT(xfs_da_node_unbalance);
+DEFINE_DA_EVENT(xfs_da_swap_lastblock);
+DEFINE_DA_EVENT(xfs_da_grow_inode);
+DEFINE_DA_EVENT(xfs_da_shrink_inode);
+
 DECLARE_EVENT_CLASS(xfs_dir2_space_class,
        TP_PROTO(struct xfs_da_args *args, int idx),
        TP_ARGS(args, idx),
index f4b2effe03334e0e52807d7934217803e7aba9f2..6fbc4cab583436399ef7f9f61da1cc6845e5dc79 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/sched.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/div64.h>
 #include <asm/acpi.h>
index e37963c1df4da6ee5c586b455b22efdb919e035e..1ced6413ea0345580830394554e0ed2b69ba1224 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef __ASM_GENERIC_ATOMIC_H
 #define __ASM_GENERIC_ATOMIC_H
 
+#include <asm/cmpxchg.h>
+
 #ifdef CONFIG_SMP
 /* Force people to define core atomics */
 # if !defined(atomic_add_return) || !defined(atomic_sub_return) || \
@@ -52,7 +54,6 @@
 #define atomic_set(v, i) (((v)->counter) = (i))
 
 #include <linux/irqflags.h>
-#include <asm/system.h>
 
 /**
  * atomic_add_return - add integer to atomic variable
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
new file mode 100644 (file)
index 0000000..639d7a4
--- /dev/null
@@ -0,0 +1,50 @@
+/* Generic barrier definitions, based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_BARRIER_H
+#define __ASM_GENERIC_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop() asm volatile ("nop")
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * This implementation only contains a compiler barrier.
+ */
+
+#define mb()   asm volatile ("": : :"memory")
+#define rmb()  mb()
+#define wmb()  asm volatile ("": : :"memory")
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#endif
+
+#define set_mb(var, value)  do { var = value;  mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#define read_barrier_depends()         do {} while (0)
+#define smp_read_barrier_depends()     do {} while (0)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_GENERIC_BARRIER_H */
index ecc44a8e2b4466fbbf86b5a1e374ae15b2ef50aa..9ae6c34dc191e73adc4b6402618a05dae773f243 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_GENERIC_BITOPS_ATOMIC_H_
 
 #include <asm/types.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
 
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
index 213ac6e8fe392b536480898e626ad3ff523a1e5d..8a361834dc25887e658107a3bf5dbf5f8142752d 100644 (file)
@@ -1,22 +1,97 @@
+/*
+ * Generic UP xchg and cmpxchg using interrupt disablement.  Does not
+ * support SMP.
+ */
+
 #ifndef __ASM_GENERIC_CMPXCHG_H
 #define __ASM_GENERIC_CMPXCHG_H
 
-/*
- * Generic cmpxchg
- *
- * Uses the local cmpxchg. Does not support SMP.
- */
 #ifdef CONFIG_SMP
 #error "Cannot use generic cmpxchg on SMP"
 #endif
 
+#include <linux/irqflags.h>
+
+#ifndef xchg
+
+/*
+ * This function doesn't exist, so you'll get a linker error if
+ * something tries to do an invalidly-sized xchg().
+ */
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline
+unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+       unsigned long ret, flags;
+
+       switch (size) {
+       case 1:
+#ifdef __xchg_u8
+               return __xchg_u8(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u8 *)ptr;
+               *(volatile u8 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u8 */
+
+       case 2:
+#ifdef __xchg_u16
+               return __xchg_u16(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u16 *)ptr;
+               *(volatile u16 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u16 */
+
+       case 4:
+#ifdef __xchg_u32
+               return __xchg_u32(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u32 *)ptr;
+               *(volatile u32 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u32 */
+
+#ifdef CONFIG_64BIT
+       case 8:
+#ifdef __xchg_u64
+               return __xchg_u64(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u64 *)ptr;
+               *(volatile u64 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u64 */
+#endif /* CONFIG_64BIT */
+
+       default:
+               __xchg_called_with_bad_pointer();
+               return x;
+       }
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#endif /* xchg */
+
 /*
  * Atomic compare and exchange.
  *
  * Do not define __HAVE_ARCH_CMPXCHG because we want to use it to check whether
  * a cmpxchg primitive faster than repeated local irq save/restore exists.
  */
+#include <asm-generic/cmpxchg-local.h>
+
 #define cmpxchg(ptr, o, n)     cmpxchg_local((ptr), (o), (n))
 #define cmpxchg64(ptr, o, n)   cmpxchg64_local((ptr), (o), (n))
 
-#endif
+#endif /* __ASM_GENERIC_CMPXCHG_H */
diff --git a/include/asm-generic/exec.h b/include/asm-generic/exec.h
new file mode 100644 (file)
index 0000000..567766b
--- /dev/null
@@ -0,0 +1,19 @@
+/* Generic process execution definitions, based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_EXEC_H
+#define __ASM_GENERIC_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_GENERIC_EXEC_H */
index 1ff4e221cb4dfc705e58ff7155835c0c68459dc9..5f52690c3c8f3a632350d14b1511908299887efb 100644 (file)
@@ -142,9 +142,9 @@ extern int __must_check gpiochip_reserve(int start, int ngpio);
 /* add/remove chips */
 extern int gpiochip_add(struct gpio_chip *chip);
 extern int __must_check gpiochip_remove(struct gpio_chip *chip);
-extern struct gpio_chip *gpiochip_find(void *data,
+extern struct gpio_chip *gpiochip_find(const void *data,
                                        int (*match)(struct gpio_chip *chip,
-                                                    void *data));
+                                                    const void *data));
 
 
 /* Always use the library code for GPIO management calls,
index 3dab00860e7183f555c10130f683a716f2d2b448..91d44bd4dde32574bb6365a5526ac33a19992050 100644 (file)
  * architectures, so that you can override them.
  */
 
+#ifndef __kernel_long_t
+typedef long           __kernel_long_t;
+typedef unsigned long  __kernel_ulong_t;
+#endif
+
 #ifndef __kernel_ino_t
-typedef unsigned long  __kernel_ino_t;
+typedef __kernel_ulong_t __kernel_ino_t;
 #endif
 
 #ifndef __kernel_mode_t
@@ -19,7 +24,7 @@ typedef unsigned int  __kernel_mode_t;
 #endif
 
 #ifndef __kernel_nlink_t
-typedef unsigned long  __kernel_nlink_t;
+typedef __kernel_ulong_t __kernel_nlink_t;
 #endif
 
 #ifndef __kernel_pid_t
@@ -36,7 +41,7 @@ typedef unsigned int  __kernel_gid_t;
 #endif
 
 #ifndef __kernel_suseconds_t
-typedef long           __kernel_suseconds_t;
+typedef __kernel_long_t                __kernel_suseconds_t;
 #endif
 
 #ifndef __kernel_daddr_t
@@ -44,8 +49,8 @@ typedef int           __kernel_daddr_t;
 #endif
 
 #ifndef __kernel_uid32_t
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
+typedef unsigned int   __kernel_uid32_t;
+typedef unsigned int   __kernel_gid32_t;
 #endif
 
 #ifndef __kernel_old_uid_t
@@ -67,99 +72,29 @@ typedef unsigned int        __kernel_size_t;
 typedef int            __kernel_ssize_t;
 typedef int            __kernel_ptrdiff_t;
 #else
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
-typedef long           __kernel_ptrdiff_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_long_t        __kernel_ssize_t;
+typedef __kernel_long_t        __kernel_ptrdiff_t;
 #endif
 #endif
 
+#ifndef __kernel_fsid_t
+typedef struct {
+       int     val[2];
+} __kernel_fsid_t;
+#endif
+
 /*
  * anything below here should be completely generic
  */
-typedef long           __kernel_off_t;
+typedef __kernel_long_t        __kernel_off_t;
 typedef long long      __kernel_loff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_clock_t;
+typedef __kernel_long_t        __kernel_time_t;
+typedef __kernel_long_t        __kernel_clock_t;
 typedef int            __kernel_timer_t;
 typedef int            __kernel_clockid_t;
 typedef char *         __kernel_caddr_t;
 typedef unsigned short __kernel_uid16_t;
 typedef unsigned short __kernel_gid16_t;
 
-typedef struct {
-       int     val[2];
-} __kernel_fsid_t;
-
-#ifdef __KERNEL__
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
-       unsigned long __tmp = __fd / __NFDBITS;
-       unsigned long __rem = __fd % __NFDBITS;
-       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *__p)
-{
-       unsigned long *__tmp = __p->fds_bits;
-       int __i;
-
-       if (__builtin_constant_p(__FDSET_LONGS)) {
-               switch (__FDSET_LONGS) {
-               case 16:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       __tmp[ 8] = 0; __tmp[ 9] = 0;
-                       __tmp[10] = 0; __tmp[11] = 0;
-                       __tmp[12] = 0; __tmp[13] = 0;
-                       __tmp[14] = 0; __tmp[15] = 0;
-                       return;
-
-               case 8:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       __tmp[ 4] = 0; __tmp[ 5] = 0;
-                       __tmp[ 6] = 0; __tmp[ 7] = 0;
-                       return;
-
-               case 4:
-                       __tmp[ 0] = 0; __tmp[ 1] = 0;
-                       __tmp[ 2] = 0; __tmp[ 3] = 0;
-                       return;
-               }
-       }
-       __i = __FDSET_LONGS;
-       while (__i) {
-               __i--;
-               *__tmp = 0;
-               __tmp++;
-       }
-}
-
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_GENERIC_POSIX_TYPES_H */
diff --git a/include/asm-generic/switch_to.h b/include/asm-generic/switch_to.h
new file mode 100644 (file)
index 0000000..052c4ac
--- /dev/null
@@ -0,0 +1,30 @@
+/* Generic task switch macro wrapper, based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_SWITCH_TO_H
+#define __ASM_GENERIC_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+/*
+ * Context switching is now performed out-of-line in switch_to.S
+ */
+extern struct task_struct *__switch_to(struct task_struct *,
+                                      struct task_struct *);
+
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               ((last) = __switch_to((prev), (next)));                 \
+       } while (0)
+
+#endif /* __ASM_GENERIC_SWITCH_TO_H */
diff --git a/include/asm-generic/system.h b/include/asm-generic/system.h
deleted file mode 100644 (file)
index 215efa7..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/* Generic system definitions, based on MN10300 definitions.
- *
- * It should be possible to use these on really simple architectures,
- * but it serves more as a starting point for new ports.
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef __ASM_GENERIC_SYSTEM_H
-#define __ASM_GENERIC_SYSTEM_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-#include <asm/cmpxchg-local.h>
-#include <asm/cmpxchg.h>
-
-struct task_struct;
-
-/* context switching is now performed out-of-line in switch_to.S */
-extern struct task_struct *__switch_to(struct task_struct *,
-               struct task_struct *);
-#define switch_to(prev, next, last)                                    \
-       do {                                                            \
-               ((last) = __switch_to((prev), (next)));                 \
-       } while (0)
-
-#define arch_align_stack(x) (x)
-
-#define nop() asm volatile ("nop")
-
-#endif /* !__ASSEMBLY__ */
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * This implementation only contains a compiler barrier.
- */
-
-#define mb()   asm volatile ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#endif
-
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-/*
- * we make sure local_irq_enable() doesn't cause priority inversion
- */
-#ifndef __ASSEMBLY__
-
-/* This function doesn't exist, so you'll get a linker error
- *    if something tries to do an invalid xchg().  */
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline
-unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long ret, flags;
-
-       switch (size) {
-       case 1:
-#ifdef __xchg_u8
-               return __xchg_u8(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u8 *)ptr;
-               *(volatile u8 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u8 */
-
-       case 2:
-#ifdef __xchg_u16
-               return __xchg_u16(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u16 *)ptr;
-               *(volatile u16 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u16 */
-
-       case 4:
-#ifdef __xchg_u32
-               return __xchg_u32(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u32 *)ptr;
-               *(volatile u32 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u32 */
-
-#ifdef CONFIG_64BIT
-       case 8:
-#ifdef __xchg_u64
-               return __xchg_u64(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u64 *)ptr;
-               *(volatile u64 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u64 */
-#endif /* CONFIG_64BIT */
-
-       default:
-               __xchg_called_with_bad_pointer();
-               return x;
-       }
-}
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __ASM_GENERIC_SYSTEM_H */
index 2292d1af9d705f129ae523ce00a6b7794fb1648c..991ef01cd77eac4fa6b9469dc2ad4c53640f3950 100644 (file)
@@ -218,7 +218,7 @@ __SC_COMP(__NR_pwritev, sys_pwritev, compat_sys_pwritev)
 
 /* fs/sendfile.c */
 #define __NR3264_sendfile 71
-__SC_3264(__NR3264_sendfile, sys_sendfile64, sys_sendfile)
+__SYSCALL(__NR3264_sendfile, sys_sendfile64)
 
 /* fs/select.c */
 #define __NR_pselect6 72
index 798603e8ec38e017e342fff7d4e2ea536ed42922..8aeadf6b553a11346aa5a5a256df1303416535e9 100644 (file)
                *(.init.setup)                                          \
                VMLINUX_SYMBOL(__setup_end) = .;
 
-#define INITCALLS                                                      \
-       *(.initcallearly.init)                                          \
-       VMLINUX_SYMBOL(__early_initcall_end) = .;                       \
-       *(.initcall0.init)                                              \
-       *(.initcall0s.init)                                             \
-       *(.initcall1.init)                                              \
-       *(.initcall1s.init)                                             \
-       *(.initcall2.init)                                              \
-       *(.initcall2s.init)                                             \
-       *(.initcall3.init)                                              \
-       *(.initcall3s.init)                                             \
-       *(.initcall4.init)                                              \
-       *(.initcall4s.init)                                             \
-       *(.initcall5.init)                                              \
-       *(.initcall5s.init)                                             \
-       *(.initcallrootfs.init)                                         \
-       *(.initcall6.init)                                              \
-       *(.initcall6s.init)                                             \
-       *(.initcall7.init)                                              \
-       *(.initcall7s.init)
+#define INIT_CALLS_LEVEL(level)                                                \
+               VMLINUX_SYMBOL(__initcall##level##_start) = .;          \
+               *(.initcall##level##.init)                              \
+               *(.initcall##level##s.init)                             \
 
 #define INIT_CALLS                                                     \
                VMLINUX_SYMBOL(__initcall_start) = .;                   \
-               INITCALLS                                               \
+               *(.initcallearly.init)                                  \
+               INIT_CALLS_LEVEL(0)                                     \
+               INIT_CALLS_LEVEL(1)                                     \
+               INIT_CALLS_LEVEL(2)                                     \
+               INIT_CALLS_LEVEL(3)                                     \
+               INIT_CALLS_LEVEL(4)                                     \
+               INIT_CALLS_LEVEL(5)                                     \
+               INIT_CALLS_LEVEL(rootfs)                                \
+               INIT_CALLS_LEVEL(6)                                     \
+               INIT_CALLS_LEVEL(7)                                     \
                VMLINUX_SYMBOL(__initcall_end) = .;
 
 #define CON_INITCALL                                                   \
index a2555538109733da56f3feffd523cf2cdef58ca9..a4b5da2b83f543ff4e503d2c15fd24aa6e04881f 100644 (file)
@@ -357,6 +357,7 @@ header-y += suspend_ioctls.h
 header-y += swab.h
 header-y += synclink.h
 header-y += sysctl.h
+header-y += sysinfo.h
 header-y += taskstats.h
 header-y += tcp.h
 header-y += telephony.h
index 3f968665899b9cadeef825dab03666d04eac3c64..f53fea61f40a4edc0456f11ae27586ebf1a3eb6f 100644 (file)
@@ -151,6 +151,7 @@ extern int ec_write(u8 addr, u8 val);
 extern int ec_transaction(u8 command,
                           const u8 *wdata, unsigned wdata_len,
                           u8 *rdata, unsigned rdata_len);
+extern acpi_handle ec_get_handle(void);
 
 #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
 
index 2c8731664180242ad95fa91cfb2b8e6d11f90b78..86fa7a71336a1cc2ea007c7410e3ede14807ec4c 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
-typedef unsigned long  aio_context_t;
+typedef __kernel_ulong_t aio_context_t;
 
 enum {
        IOCB_CMD_PREAD = 0,
index 033f6aa670de5086ba64dcde7ee6ab7c80e269a7..e64ce2cfee9959f5b231b879d3afef2b5abd57cc 100644 (file)
@@ -47,9 +47,6 @@ enum {
  * @muxval: a number usually used to poke into some mux regiser to
  * mux in the signal to this channel
  * @cctl_opt: default options for the channel control register
- * @device_fc: Flow Controller Settings for ccfg register. Only valid for slave
- * channels. Fill with 'true' if peripheral should be flow controller. Direction
- * will be selected at Runtime.
  * @addr: source/target address in physical memory for this DMA channel,
  * can be the address of a FIFO register for burst requests for example.
  * This can be left undefined if the PrimeCell API is used for configuring
@@ -68,7 +65,6 @@ struct pl08x_channel_data {
        int max_signal;
        u32 muxval;
        u32 cctl;
-       bool device_fc;
        dma_addr_t addr;
        bool circular_buffer;
        bool single;
@@ -176,13 +172,15 @@ enum pl08x_dma_chan_state {
  * @runtime_addr: address for RX/TX according to the runtime config
  * @runtime_direction: current direction of this channel according to
  * runtime config
- * @lc: last completed transaction on this channel
  * @pend_list: queued transactions pending on this channel
  * @at: active transaction on this channel
  * @lock: a lock for this channel data
  * @host: a pointer to the host (internal use)
  * @state: whether the channel is idle, paused, running etc
  * @slave: whether this channel is a device (slave) or for memcpy
+ * @device_fc: Flow Controller Settings for ccfg register. Only valid for slave
+ * channels. Fill with 'true' if peripheral should be flow controller. Direction
+ * will be selected at Runtime.
  * @waiting: a TX descriptor on this channel which is waiting for a physical
  * channel to become available
  */
@@ -198,13 +196,13 @@ struct pl08x_dma_chan {
        u32 src_cctl;
        u32 dst_cctl;
        enum dma_transfer_direction runtime_direction;
-       dma_cookie_t lc;
        struct list_head pend_list;
        struct pl08x_txd *at;
        spinlock_t lock;
        struct pl08x_driver_data *host;
        enum pl08x_dma_chan_state state;
        bool slave;
+       bool device_fc;
        struct pl08x_txd *waiting;
 };
 
index 12e023c19ac18270adf34d0ddf9675af3e3cc609..fe93758e84036b8abd8a2b5c5191c0545050094b 100644 (file)
@@ -13,7 +13,6 @@
 #define        __AMBA_PL330_H_
 
 #include <linux/dmaengine.h>
-#include <asm/hardware/pl330.h>
 
 struct dma_pl330_platdata {
        /*
diff --git a/include/linux/apple_bl.h b/include/linux/apple_bl.h
new file mode 100644 (file)
index 0000000..47bedc0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * apple_bl exported symbols
+ */
+
+#ifndef _LINUX_APPLE_BL_H
+#define _LINUX_APPLE_BL_H
+
+#ifdef CONFIG_BACKLIGHT_APPLE
+
+extern int apple_bl_register(void);
+extern void apple_bl_unregister(void);
+
+#else /* !CONFIG_BACKLIGHT_APPLE */
+
+static inline int apple_bl_register(void)
+{
+       return 0;
+}
+
+static inline void apple_bl_unregister(void)
+{
+}
+
+#endif /* !CONFIG_BACKLIGHT_APPLE */
+
+#endif /* _LINUX_APPLE_BL_H */
index e3d8bf26e5eb229a9ca2959fc5ea2b1638238988..aa629bce903340b48049028e2bc8211d1bb62363 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 /* this is used only to give gcc a clue about good code generation */
 union cnt32_to_63 {
index 7e05fcee75a158815986fe9477fbbf98bde50052..5d46217f84adfaab0dbe679a7612da7062bb72c6 100644 (file)
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 
+#ifndef COMPAT_USE_64BIT_TIME
+#define COMPAT_USE_64BIT_TIME 0
+#endif
+
 #define compat_jiffies_to_clock_t(x)   \
                (((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
@@ -83,10 +87,26 @@ typedef struct {
        compat_sigset_word      sig[_COMPAT_NSIG_WORDS];
 } compat_sigset_t;
 
+/*
+ * These functions operate strictly on struct compat_time*
+ */
 extern int get_compat_timespec(struct timespec *,
                               const struct compat_timespec __user *);
 extern int put_compat_timespec(const struct timespec *,
                               struct compat_timespec __user *);
+extern int get_compat_timeval(struct timeval *,
+                             const struct compat_timeval __user *);
+extern int put_compat_timeval(const struct timeval *,
+                             struct compat_timeval __user *);
+/*
+ * These functions operate on 32- or 64-bit specs depending on
+ * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments and the
+ * naming as compat_get/put_ rather than get/put_compat_.
+ */
+extern int compat_get_timespec(struct timespec *, const void __user *);
+extern int compat_put_timespec(const struct timespec *, void __user *);
+extern int compat_get_timeval(struct timeval *, const void __user *);
+extern int compat_put_timeval(const struct timeval *, void __user *);
 
 struct compat_iovec {
        compat_uptr_t   iov_base;
@@ -224,6 +244,7 @@ struct compat_sysinfo;
 struct compat_sysctl_args;
 struct compat_kexec_segment;
 struct compat_mq_attr;
+struct compat_msgbuf;
 
 extern void compat_exit_robust_list(struct task_struct *curr);
 
@@ -234,13 +255,22 @@ asmlinkage long
 compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
                           compat_size_t __user *len_ptr);
 
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 long compat_sys_semctl(int first, int second, int third, void __user *uptr);
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
                int version, void __user *uptr);
-long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
                void __user *uptr);
+#else
+long compat_sys_semctl(int semid, int semnum, int cmd, int arg);
+long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
+               size_t msgsz, int msgflg);
+long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
+               size_t msgsz, long msgtyp, int msgflg);
+long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg);
+#endif
+long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmctl(int first, int second, void __user *uptr);
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
                unsigned nsems, const struct compat_timespec __user *timeout);
index 7b9b75a529be04fef475c57b30bf351e19695e7b..1ffdb9856bb9fcc0592a939e98de7447e10266af 100644 (file)
@@ -810,11 +810,10 @@ static inline const struct cpumask *get_cpu_mask(unsigned int cpu)
 #else /* NR_CPUS > 1 */
 int __first_cpu(const cpumask_t *srcp);
 int __next_cpu(int n, const cpumask_t *srcp);
-int __any_online_cpu(const cpumask_t *mask);
 
 #define first_cpu(src)         __first_cpu(&(src))
 #define next_cpu(n, src)       __next_cpu((n), &(src))
-#define any_online_cpu(mask) __any_online_cpu(&(mask))
+#define any_online_cpu(mask) cpumask_any_and(&mask, cpu_online_mask)
 #define for_each_cpu_mask(cpu, mask)                   \
        for ((cpu) = -1;                                \
                (cpu) = next_cpu((cpu), (mask)),        \
index 7a7e5fd2a27784e3307e3351c92abd4240aba2db..668f66baac7b245a4ac6deb3cd9842c12f640e4e 100644 (file)
@@ -22,7 +22,7 @@ extern int cpuset_init(void);
 extern void cpuset_init_smp(void);
 extern void cpuset_update_active_cpus(void);
 extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
-extern int cpuset_cpus_allowed_fallback(struct task_struct *p);
+extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
 extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
 #define cpuset_current_mems_allowed (current->mems_allowed)
 void cpuset_init_current_mems_allowed(void);
@@ -135,10 +135,8 @@ static inline void cpuset_cpus_allowed(struct task_struct *p,
        cpumask_copy(mask, cpu_possible_mask);
 }
 
-static inline int cpuset_cpus_allowed_fallback(struct task_struct *p)
+static inline void cpuset_cpus_allowed_fallback(struct task_struct *p)
 {
-       do_set_cpus_allowed(p, cpu_possible_mask);
-       return cpumask_any(cpu_active_mask);
 }
 
 static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
index 94f20c1488a19cff3b21e9da5e58d3114c23ffcf..3bd46f766751caa9b143adcc5ce546441f6b868d 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/bug.h>
-#include <asm/system.h>
 
 struct task_struct;
 
index 887dcd487062d5f892a968056a6c339e8d6d7623..3efbfc2145c3ad97412392700a4992b534a8dc5b 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/scatterlist.h>
 #include <linux/list.h>
 #include <linux/dma-mapping.h>
+#include <linux/fs.h>
 
 struct device;
 struct dma_buf;
@@ -49,6 +50,17 @@ struct dma_buf_attachment;
  * @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter
  *                pages.
  * @release: release this buffer; to be called after the last dma_buf_put.
+ * @begin_cpu_access: [optional] called before cpu access to invalidate cpu
+ *                   caches and allocate backing storage (if not yet done)
+ *                   respectively pin the objet into memory.
+ * @end_cpu_access: [optional] called after cpu access to flush cashes.
+ * @kmap_atomic: maps a page from the buffer into kernel address
+ *              space, users may not block until the subsequent unmap call.
+ *              This callback must not sleep.
+ * @kunmap_atomic: [optional] unmaps a atomically mapped page from the buffer.
+ *                This Callback must not sleep.
+ * @kmap: maps a page from the buffer into kernel address space.
+ * @kunmap: [optional] unmaps a page from the buffer.
  */
 struct dma_buf_ops {
        int (*attach)(struct dma_buf *, struct device *,
@@ -63,7 +75,8 @@ struct dma_buf_ops {
        struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
                                                enum dma_data_direction);
        void (*unmap_dma_buf)(struct dma_buf_attachment *,
-                                               struct sg_table *);
+                                               struct sg_table *,
+                                               enum dma_data_direction);
        /* TODO: Add try_map_dma_buf version, to return immed with -EBUSY
         * if the call would block.
         */
@@ -71,6 +84,14 @@ struct dma_buf_ops {
        /* after final dma_buf_put() */
        void (*release)(struct dma_buf *);
 
+       int (*begin_cpu_access)(struct dma_buf *, size_t, size_t,
+                               enum dma_data_direction);
+       void (*end_cpu_access)(struct dma_buf *, size_t, size_t,
+                              enum dma_data_direction);
+       void *(*kmap_atomic)(struct dma_buf *, unsigned long);
+       void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *);
+       void *(*kmap)(struct dma_buf *, unsigned long);
+       void (*kunmap)(struct dma_buf *, unsigned long, void *);
 };
 
 /**
@@ -86,7 +107,7 @@ struct dma_buf {
        struct file *file;
        struct list_head attachments;
        const struct dma_buf_ops *ops;
-       /* mutex to serialize list manipulation and other ops */
+       /* mutex to serialize list manipulation and attach/detach */
        struct mutex lock;
        void *priv;
 };
@@ -109,20 +130,43 @@ struct dma_buf_attachment {
        void *priv;
 };
 
+/**
+ * get_dma_buf - convenience wrapper for get_file.
+ * @dmabuf:    [in]    pointer to dma_buf
+ *
+ * Increments the reference count on the dma-buf, needed in case of drivers
+ * that either need to create additional references to the dmabuf on the
+ * kernel side.  For example, an exporter that needs to keep a dmabuf ptr
+ * so that subsequent exports don't create a new dmabuf.
+ */
+static inline void get_dma_buf(struct dma_buf *dmabuf)
+{
+       get_file(dmabuf->file);
+}
+
 #ifdef CONFIG_DMA_SHARED_BUFFER
 struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
                                                        struct device *dev);
 void dma_buf_detach(struct dma_buf *dmabuf,
                                struct dma_buf_attachment *dmabuf_attach);
-struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
-                       size_t size, int flags);
-int dma_buf_fd(struct dma_buf *dmabuf);
+struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
+                              size_t size, int flags);
+int dma_buf_fd(struct dma_buf *dmabuf, int flags);
 struct dma_buf *dma_buf_get(int fd);
 void dma_buf_put(struct dma_buf *dmabuf);
 
 struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
                                        enum dma_data_direction);
-void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *);
+void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
+                               enum dma_data_direction);
+int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size_t len,
+                            enum dma_data_direction dir);
+void dma_buf_end_cpu_access(struct dma_buf *dma_buf, size_t start, size_t len,
+                           enum dma_data_direction dir);
+void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
+void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
+void *dma_buf_kmap(struct dma_buf *, unsigned long);
+void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
 #else
 
 static inline struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
@@ -138,13 +182,13 @@ static inline void dma_buf_detach(struct dma_buf *dmabuf,
 }
 
 static inline struct dma_buf *dma_buf_export(void *priv,
-                                               struct dma_buf_ops *ops,
-                                               size_t size, int flags)
+                                            const struct dma_buf_ops *ops,
+                                            size_t size, int flags)
 {
        return ERR_PTR(-ENODEV);
 }
 
-static inline int dma_buf_fd(struct dma_buf *dmabuf)
+static inline int dma_buf_fd(struct dma_buf *dmabuf, int flags)
 {
        return -ENODEV;
 }
@@ -166,11 +210,44 @@ static inline struct sg_table *dma_buf_map_attachment(
 }
 
 static inline void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
-                                               struct sg_table *sg)
+                       struct sg_table *sg, enum dma_data_direction dir)
 {
        return;
 }
 
+static inline int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+                                          size_t start, size_t len,
+                                          enum dma_data_direction dir)
+{
+       return -ENODEV;
+}
+
+static inline void dma_buf_end_cpu_access(struct dma_buf *dmabuf,
+                                         size_t start, size_t len,
+                                         enum dma_data_direction dir)
+{
+}
+
+static inline void *dma_buf_kmap_atomic(struct dma_buf *dmabuf,
+                                       unsigned long pnum)
+{
+       return NULL;
+}
+
+static inline void dma_buf_kunmap_atomic(struct dma_buf *dmabuf,
+                                        unsigned long pnum, void *vaddr)
+{
+}
+
+static inline void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long pnum)
+{
+       return NULL;
+}
+
+static inline void dma_buf_kunmap(struct dma_buf *dmabuf,
+                                 unsigned long pnum, void *vaddr)
+{
+}
 #endif /* CONFIG_DMA_SHARED_BUFFER */
 
 #endif /* __DMA_BUF_H__ */
index e13117cbd2f7daefa62d067124cbd815b860aea9..5a736af3cc7a3623574794554ab510c29c596a30 100644 (file)
@@ -77,7 +77,7 @@ static inline u64 dma_get_mask(struct device *dev)
        return DMA_BIT_MASK(32);
 }
 
-#ifdef ARCH_HAS_DMA_SET_COHERENT_MASK
+#ifdef CONFIG_ARCH_HAS_DMA_SET_COHERENT_MASK
 int dma_set_coherent_mask(struct device *dev, u64 mask);
 #else
 static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
index a5966f691ef836954ae1bbee69697c81e98590bd..676f967390aeb8ccfe4983a9fab04285d62ce58d 100644 (file)
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
-#ifndef DMAENGINE_H
-#define DMAENGINE_H
+#ifndef LINUX_DMAENGINE_H
+#define LINUX_DMAENGINE_H
 
 #include <linux/device.h>
 #include <linux/uio.h>
 #include <linux/bug.h>
 #include <linux/scatterlist.h>
 #include <linux/bitmap.h>
+#include <linux/types.h>
 #include <asm/page.h>
 
 /**
@@ -258,6 +259,7 @@ struct dma_chan_percpu {
  * struct dma_chan - devices supply DMA channels, clients use them
  * @device: ptr to the dma device who supplies this channel, always !%NULL
  * @cookie: last cookie value returned to client
+ * @completed_cookie: last completed cookie for this channel
  * @chan_id: channel ID for sysfs
  * @dev: class device for sysfs
  * @device_node: used to add this to the device chan list
@@ -269,6 +271,7 @@ struct dma_chan_percpu {
 struct dma_chan {
        struct dma_device *device;
        dma_cookie_t cookie;
+       dma_cookie_t completed_cookie;
 
        /* sysfs */
        int chan_id;
@@ -332,6 +335,9 @@ enum dma_slave_buswidth {
  * may or may not be applicable on memory sources.
  * @dst_maxburst: same as src_maxburst but for destination target
  * mutatis mutandis.
+ * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill
+ * with 'true' if peripheral should be flow controller. Direction will be
+ * selected at Runtime.
  *
  * This struct is passed in as configuration data to a DMA engine
  * in order to set up a certain channel for DMA transport at runtime.
@@ -358,6 +364,7 @@ struct dma_slave_config {
        enum dma_slave_buswidth dst_addr_width;
        u32 src_maxburst;
        u32 dst_maxburst;
+       bool device_fc;
 };
 
 static inline const char *dma_chan_name(struct dma_chan *chan)
@@ -576,10 +583,11 @@ struct dma_device {
        struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
-               unsigned long flags);
+               unsigned long flags, void *context);
        struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
                struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-               size_t period_len, enum dma_transfer_direction direction);
+               size_t period_len, enum dma_transfer_direction direction,
+               void *context);
        struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
                struct dma_chan *chan, struct dma_interleaved_template *xt,
                unsigned long flags);
@@ -613,7 +621,24 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
        struct scatterlist sg;
        sg_init_one(&sg, buf, len);
 
-       return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags);
+       return chan->device->device_prep_slave_sg(chan, &sg, 1,
+                                                 dir, flags, NULL);
+}
+
+static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
+       struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+       enum dma_transfer_direction dir, unsigned long flags)
+{
+       return chan->device->device_prep_slave_sg(chan, sgl, sg_len,
+                                                 dir, flags, NULL);
+}
+
+static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
+               struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+               size_t period_len, enum dma_transfer_direction dir)
+{
+       return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len,
+                                               period_len, dir, NULL);
 }
 
 static inline int dmaengine_terminate_all(struct dma_chan *chan)
index f2c64f92c4a006394e21e022bcf6b5c03590c930..2412e02d7c0f78796202315002474c09c7c7558a 100644 (file)
@@ -31,18 +31,6 @@ struct dw_dma_platform_data {
        unsigned char   chan_priority;
 };
 
-/**
- * enum dw_dma_slave_width - DMA slave register access width.
- * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
- * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
- * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
- */
-enum dw_dma_slave_width {
-       DW_DMA_SLAVE_WIDTH_8BIT,
-       DW_DMA_SLAVE_WIDTH_16BIT,
-       DW_DMA_SLAVE_WIDTH_32BIT,
-};
-
 /* bursts size */
 enum dw_dma_msize {
        DW_DMA_MSIZE_1,
@@ -55,47 +43,21 @@ enum dw_dma_msize {
        DW_DMA_MSIZE_256,
 };
 
-/* flow controller */
-enum dw_dma_fc {
-       DW_DMA_FC_D_M2M,
-       DW_DMA_FC_D_M2P,
-       DW_DMA_FC_D_P2M,
-       DW_DMA_FC_D_P2P,
-       DW_DMA_FC_P_P2M,
-       DW_DMA_FC_SP_P2P,
-       DW_DMA_FC_P_M2P,
-       DW_DMA_FC_DP_P2P,
-};
-
 /**
  * struct dw_dma_slave - Controller-specific information about a slave
  *
  * @dma_dev: required DMA master device
- * @tx_reg: physical address of data register used for
- *     memory-to-peripheral transfers
- * @rx_reg: physical address of data register used for
- *     peripheral-to-memory transfers
- * @reg_width: peripheral register width
  * @cfg_hi: Platform-specific initializer for the CFG_HI register
  * @cfg_lo: Platform-specific initializer for the CFG_LO register
  * @src_master: src master for transfers on allocated channel.
  * @dst_master: dest master for transfers on allocated channel.
- * @src_msize: src burst size.
- * @dst_msize: dest burst size.
- * @fc: flow controller for DMA transfer
  */
 struct dw_dma_slave {
        struct device           *dma_dev;
-       dma_addr_t              tx_reg;
-       dma_addr_t              rx_reg;
-       enum dw_dma_slave_width reg_width;
        u32                     cfg_hi;
        u32                     cfg_lo;
        u8                      src_master;
        u8                      dst_master;
-       u8                      src_msize;
-       u8                      dst_msize;
-       u8                      fc;
 };
 
 /* Platform-configurable bits in CFG_HI */
index ba317e2930a19c78741f93379d6d3d259821b99a..c621d762bb2c9d18fd4ccda585c78491cafb1730 100644 (file)
@@ -70,25 +70,64 @@ enum dev_type {
 #define DEV_FLAG_X32           BIT(DEV_X32)
 #define DEV_FLAG_X64           BIT(DEV_X64)
 
-/* memory types */
+/**
+ * enum mem_type - memory types. For a more detailed reference, please see
+ *                     http://en.wikipedia.org/wiki/DRAM
+ *
+ * @MEM_EMPTY          Empty csrow
+ * @MEM_RESERVED:      Reserved csrow type
+ * @MEM_UNKNOWN:       Unknown csrow type
+ * @MEM_FPM:           FPM - Fast Page Mode, used on systems up to 1995.
+ * @MEM_EDO:           EDO - Extended data out, used on systems up to 1998.
+ * @MEM_BEDO:          BEDO - Burst Extended data out, an EDO variant.
+ * @MEM_SDR:           SDR - Single data rate SDRAM
+ *                     http://en.wikipedia.org/wiki/Synchronous_dynamic_random-access_memory
+ *                     They use 3 pins for chip select: Pins 0 and 2 are
+ *                     for rank 0; pins 1 and 3 are for rank 1, if the memory
+ *                     is dual-rank.
+ * @MEM_RDR:           Registered SDR SDRAM
+ * @MEM_DDR:           Double data rate SDRAM
+ *                     http://en.wikipedia.org/wiki/DDR_SDRAM
+ * @MEM_RDDR:          Registered Double data rate SDRAM
+ *                     This is a variant of the DDR memories.
+ *                     A registered memory has a buffer inside it, hiding
+ *                     part of the memory details to the memory controller.
+ * @MEM_RMBS:          Rambus DRAM, used on a few Pentium III/IV controllers.
+ * @MEM_DDR2:          DDR2 RAM, as described at JEDEC JESD79-2F.
+ *                     Those memories are labed as "PC2-" instead of "PC" to
+ *                     differenciate from DDR.
+ * @MEM_FB_DDR2:       Fully-Buffered DDR2, as described at JEDEC Std No. 205
+ *                     and JESD206.
+ *                     Those memories are accessed per DIMM slot, and not by
+ *                     a chip select signal.
+ * @MEM_RDDR2:         Registered DDR2 RAM
+ *                     This is a variant of the DDR2 memories.
+ * @MEM_XDR:           Rambus XDR
+ *                     It is an evolution of the original RAMBUS memories,
+ *                     created to compete with DDR2. Weren't used on any
+ *                     x86 arch, but cell_edac PPC memory controller uses it.
+ * @MEM_DDR3:          DDR3 RAM
+ * @MEM_RDDR3:         Registered DDR3 RAM
+ *                     This is a variant of the DDR3 memories.
+ */
 enum mem_type {
-       MEM_EMPTY = 0,          /* Empty csrow */
-       MEM_RESERVED,           /* Reserved csrow type */
-       MEM_UNKNOWN,            /* Unknown csrow type */
-       MEM_FPM,                /* Fast page mode */
-       MEM_EDO,                /* Extended data out */
-       MEM_BEDO,               /* Burst Extended data out */
-       MEM_SDR,                /* Single data rate SDRAM */
-       MEM_RDR,                /* Registered single data rate SDRAM */
-       MEM_DDR,                /* Double data rate SDRAM */
-       MEM_RDDR,               /* Registered Double data rate SDRAM */
-       MEM_RMBS,               /* Rambus DRAM */
-       MEM_DDR2,               /* DDR2 RAM */
-       MEM_FB_DDR2,            /* fully buffered DDR2 */
-       MEM_RDDR2,              /* Registered DDR2 RAM */
-       MEM_XDR,                /* Rambus XDR */
-       MEM_DDR3,               /* DDR3 RAM */
-       MEM_RDDR3,              /* Registered DDR3 RAM */
+       MEM_EMPTY = 0,
+       MEM_RESERVED,
+       MEM_UNKNOWN,
+       MEM_FPM,
+       MEM_EDO,
+       MEM_BEDO,
+       MEM_SDR,
+       MEM_RDR,
+       MEM_DDR,
+       MEM_RDDR,
+       MEM_RMBS,
+       MEM_DDR2,
+       MEM_FB_DDR2,
+       MEM_RDDR2,
+       MEM_XDR,
+       MEM_DDR3,
+       MEM_RDDR3,
 };
 
 #define MEM_FLAG_EMPTY         BIT(MEM_EMPTY)
@@ -166,8 +205,9 @@ enum scrub_type {
 #define OP_OFFLINE             0x300
 
 /*
- * There are several things to be aware of that aren't at all obvious:
+ * Concepts used at the EDAC subsystem
  *
+ * There are several things to be aware of that aren't at all obvious:
  *
  * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
  *
@@ -176,36 +216,61 @@ enum scrub_type {
  * creating a common ground for discussion, terms and their definitions
  * will be established.
  *
- * Memory devices:     The individual chip on a memory stick.  These devices
- *                     commonly output 4 and 8 bits each.  Grouping several
- *                     of these in parallel provides 64 bits which is common
- *                     for a memory stick.
+ * Memory devices:     The individual DRAM chips on a memory stick.  These
+ *                     devices commonly output 4 and 8 bits each (x4, x8).
+ *                     Grouping several of these in parallel provides the
+ *                     number of bits that the memory controller expects:
+ *                     typically 72 bits, in order to provide 64 bits +
+ *                     8 bits of ECC data.
  *
  * Memory Stick:       A printed circuit board that aggregates multiple
- *                     memory devices in parallel.  This is the atomic
- *                     memory component that is purchaseable by Joe consumer
- *                     and loaded into a memory socket.
+ *                     memory devices in parallel.  In general, this is the
+ *                     Field Replaceable Unit (FRU) which gets replaced, in
+ *                     the case of excessive errors. Most often it is also
+ *                     called DIMM (Dual Inline Memory Module).
+ *
+ * Memory Socket:      A physical connector on the motherboard that accepts
+ *                     a single memory stick. Also called as "slot" on several
+ *                     datasheets.
  *
- * Socket:             A physical connector on the motherboard that accepts
- *                     a single memory stick.
+ * Channel:            A memory controller channel, responsible to communicate
+ *                     with a group of DIMMs. Each channel has its own
+ *                     independent control (command) and data bus, and can
+ *                     be used independently or grouped with other channels.
  *
- * Channel:            Set of memory devices on a memory stick that must be
- *                     grouped in parallel with one or more additional
- *                     channels from other memory sticks.  This parallel
- *                     grouping of the output from multiple channels are
- *                     necessary for the smallest granularity of memory access.
- *                     Some memory controllers are capable of single channel -
- *                     which means that memory sticks can be loaded
- *                     individually.  Other memory controllers are only
- *                     capable of dual channel - which means that memory
- *                     sticks must be loaded as pairs (see "socket set").
+ * Branch:             It is typically the highest hierarchy on a
+ *                     Fully-Buffered DIMM memory controller.
+ *                     Typically, it contains two channels.
+ *                     Two channels at the same branch can be used in single
+ *                     mode or in lockstep mode.
+ *                     When lockstep is enabled, the cacheline is doubled,
+ *                     but it generally brings some performance penalty.
+ *                     Also, it is generally not possible to point to just one
+ *                     memory stick when an error occurs, as the error
+ *                     correction code is calculated using two DIMMs instead
+ *                     of one. Due to that, it is capable of correcting more
+ *                     errors than on single mode.
  *
- * Chip-select row:    All of the memory devices that are selected together.
- *                     for a single, minimum grain of memory access.
- *                     This selects all of the parallel memory devices across
- *                     all of the parallel channels.  Common chip-select rows
- *                     for single channel are 64 bits, for dual channel 128
- *                     bits.
+ * Single-channel:     The data accessed by the memory controller is contained
+ *                     into one dimm only. E. g. if the data is 64 bits-wide,
+ *                     the data flows to the CPU using one 64 bits parallel
+ *                     access.
+ *                     Typically used with SDR, DDR, DDR2 and DDR3 memories.
+ *                     FB-DIMM and RAMBUS use a different concept for channel,
+ *                     so this concept doesn't apply there.
+ *
+ * Double-channel:     The data size accessed by the memory controller is
+ *                     interlaced into two dimms, accessed at the same time.
+ *                     E. g. if the DIMM is 64 bits-wide (72 bits with ECC),
+ *                     the data flows to the CPU using a 128 bits parallel
+ *                     access.
+ *
+ * Chip-select row:    This is the name of the DRAM signal used to select the
+ *                     DRAM ranks to be accessed. Common chip-select rows for
+ *                     single channel are 64 bits, for dual channel 128 bits.
+ *                     It may not be visible by the memory controller, as some
+ *                     DIMM types have a memory buffer that can hide direct
+ *                     access to it from the Memory Controller.
  *
  * Single-Ranked stick:        A Single-ranked stick has 1 chip-select row of memory.
  *                     Motherboards commonly drive two chip-select pins to
@@ -218,8 +283,8 @@ enum scrub_type {
  *
  * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick.
  *                     A double-sided stick has two chip-select rows which
- *                     access different sets of memory devices.  The two
- *                     rows cannot be accessed concurrently.  "Double-sided"
+ *                     access different sets of memory devices. The two
+ *                     rows cannot be accessed concurrently. "Double-sided"
  *                     is irrespective of the memory devices being mounted
  *                     on both sides of the memory stick.
  *
@@ -247,10 +312,22 @@ enum scrub_type {
  * PS - I enjoyed writing all that about as much as you enjoyed reading it.
  */
 
-struct channel_info {
-       int chan_idx;           /* channel index */
-       u32 ce_count;           /* Correctable Errors for this CHANNEL */
-       char label[EDAC_MC_LABEL_LEN + 1];      /* DIMM label on motherboard */
+/**
+ * struct rank_info - contains the information for one DIMM rank
+ *
+ * @chan_idx:  channel number where the rank is (typically, 0 or 1)
+ * @ce_count:  number of correctable errors for this rank
+ * @label:     DIMM label. Different ranks for the same DIMM should be
+ *             filled, on userspace, with the same label.
+ *             FIXME: The core currently won't enforce it.
+ * @csrow:     A pointer to the chip select row structure (the parent
+ *             structure). The location of the rank is given by
+ *             the (csrow->csrow_idx, chan_idx) vector.
+ */
+struct rank_info {
+       int chan_idx;
+       u32 ce_count;
+       char label[EDAC_MC_LABEL_LEN + 1];
        struct csrow_info *csrow;       /* the parent */
 };
 
@@ -274,7 +351,7 @@ struct csrow_info {
 
        /* channel information for this csrow */
        u32 nr_channels;
-       struct channel_info *channels;
+       struct rank_info *channels;
 };
 
 struct mcidev_sysfs_group {
index 47fbf6b3dc779df2d6fe15c93e63fee8f884b1e3..88ec80670d5ff1da744a4a5d9174fb8c6f3512da 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/pstore.h>
 
 #include <asm/page.h>
-#include <asm/system.h>
 
 #define EFI_SUCCESS            0
 #define EFI_LOAD_ERROR          ( 1 | (1UL << (BITS_PER_LONG-1)))
index 82163c4b32c9fa89cd2869e369f0a5c39239c5c1..158a41eed3140b9b2870f419b8ca3c95ed3a4763 100644 (file)
  */
 #define NR_OPEN_DEFAULT BITS_PER_LONG
 
-/*
- * The embedded_fd_set is a small fd_set,
- * suitable for most tasks (which open <= BITS_PER_LONG files)
- */
-struct embedded_fd_set {
-       unsigned long fds_bits[1];
-};
-
 struct fdtable {
        unsigned int max_fds;
        struct file __rcu **fd;      /* current fd array */
-       fd_set *close_on_exec;
-       fd_set *open_fds;
+       unsigned long *close_on_exec;
+       unsigned long *open_fds;
        struct rcu_head rcu;
        struct fdtable *next;
 };
 
+static inline void __set_close_on_exec(int fd, struct fdtable *fdt)
+{
+       __set_bit(fd, fdt->close_on_exec);
+}
+
+static inline void __clear_close_on_exec(int fd, struct fdtable *fdt)
+{
+       __clear_bit(fd, fdt->close_on_exec);
+}
+
+static inline bool close_on_exec(int fd, const struct fdtable *fdt)
+{
+       return test_bit(fd, fdt->close_on_exec);
+}
+
+static inline void __set_open_fd(int fd, struct fdtable *fdt)
+{
+       __set_bit(fd, fdt->open_fds);
+}
+
+static inline void __clear_open_fd(int fd, struct fdtable *fdt)
+{
+       __clear_bit(fd, fdt->open_fds);
+}
+
+static inline bool fd_is_open(int fd, const struct fdtable *fdt)
+{
+       return test_bit(fd, fdt->open_fds);
+}
+
 /*
  * Open file table structure
  */
@@ -53,8 +75,8 @@ struct files_struct {
    */
        spinlock_t file_lock ____cacheline_aligned_in_smp;
        int next_fd;
-       struct embedded_fd_set close_on_exec_init;
-       struct embedded_fd_set open_fds_init;
+       unsigned long close_on_exec_init[1];
+       unsigned long open_fds_init[1];
        struct file __rcu * fd_array[NR_OPEN_DEFAULT];
 };
 
index c437f914d537746d5c856d506ef5ee6b4e520f0b..135693e79f2b0d1a86597c27b5003ff57313204d 100644 (file)
@@ -92,6 +92,10 @@ struct inodes_stat_t {
 /* File is opened using open(.., 3, ..) and is writeable only for ioctls
    (specialy hack for floppy.c) */
 #define FMODE_WRITE_IOCTL      ((__force fmode_t)0x100)
+/* 32bit hashes as llseek() offset (for directories) */
+#define FMODE_32BITHASH         ((__force fmode_t)0x200)
+/* 64bit hashes as llseek() offset (for directories) */
+#define FMODE_64BITHASH         ((__force fmode_t)0x400)
 
 /*
  * Don't update ctime and mtime.
index ed5a46707ad0d0cd229e36920aa510b4d79fb279..6155ecf192b0466f02ea616b5b8d8ef9fd5fc2f5 100644 (file)
 #define GPIOF_OUT_INIT_LOW     (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
 #define GPIOF_OUT_INIT_HIGH    (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
 
+/* Gpio pin is open drain */
+#define GPIOF_OPEN_DRAIN       (1 << 2)
+
+/* Gpio pin is open source */
+#define GPIOF_OPEN_SOURCE      (1 << 3)
+
 /**
  * struct gpio - a structure describing a GPIO with configuration
  * @gpio:      the GPIO number
index 584ffa0f328247be11729c5b6576e99eca002a31..63904ba6887ea1d1eb60881c122aa9cf182cff4f 100644 (file)
@@ -15,7 +15,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
index 0f91a957a690930cd365937e3d62a411b1f83cdf..538e8f41a319e0d05bde2080c2bb018f1578e6da 100644 (file)
@@ -16,7 +16,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
index fd53bfd2647044be7d48d26adc4de31b6c5d238e..8a7406b2114df7731fed5827e6f6696ef376d6f5 100644 (file)
@@ -16,7 +16,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
 */
 
 #ifndef _LINUX_I2C_DEV_H
index 34536effd652d38fcc82baf4862022f6c16ba73e..747f0cde41640e08cbbcc75654e7275ae4ea2baf 100644 (file)
@@ -18,7 +18,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #ifndef _LINUX_I2C_MUX_H
index 63f57a8c8b313561a59af8044593f871de3a9edc..017fb40f702ae241784b68c0b4aa61b496869491 100644 (file)
@@ -15,7 +15,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #ifndef _LINUX_I2C_SMBUS_H
index 8e25a9167f1303f3d07e63a26beb93f5d2987e98..195d8b3d9cfbf9b9363367f5604aaec029c68e20 100644 (file)
@@ -17,7 +17,8 @@
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
index 7fcab23c59cee7a7fe2fe3a2fdbadff49cb0571b..2463b61003336b0f176b5ed851aa8776a5202697 100644 (file)
@@ -761,7 +761,7 @@ struct twl_regulator_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-int twl4030_sih_setup(int module);
+int twl4030_sih_setup(struct device *dev, int module, int irq_base);
 
 /* Offsets to Power Registers */
 #define TWL4030_VDAC_DEV_GRP           0x3B
index 7afe15f916da3cf5b0ca59e83eb8900447a60705..b17974917dbf4369200901f119f670d14e0faa62 100644 (file)
@@ -22,7 +22,6 @@
 #include <acpi/acpi.h>
 #endif
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 /* for request_sense */
index 3f830e00511852a7ddd93a82f044502c80beeea4..2aea5d22db07bc08a9bd0071ac49b7ab59ab592c 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/atomic.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
index 5db52d0ff1d44ab240de7f0892e241c0c3b0922f..a5375e7f3feac423fa6325280276e17dcf5351f6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_KERNEL_H
 #define _LINUX_KERNEL_H
 
+#include <linux/sysinfo.h>
+
 /*
  * 'kernel.h' contains some often-used function prototypes etc
  */
@@ -698,27 +700,8 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
 #endif
 
-struct sysinfo;
 extern int do_sysinfo(struct sysinfo *info);
 
 #endif /* __KERNEL__ */
 
-#define SI_LOAD_SHIFT  16
-struct sysinfo {
-       long uptime;                    /* Seconds since boot */
-       unsigned long loads[3];         /* 1, 5, and 15 minute load averages */
-       unsigned long totalram;         /* Total usable main memory size */
-       unsigned long freeram;          /* Available memory size */
-       unsigned long sharedram;        /* Amount of shared memory */
-       unsigned long bufferram;        /* Memory used by buffers */
-       unsigned long totalswap;        /* Total swap space size */
-       unsigned long freeswap;         /* swap space still available */
-       unsigned short procs;           /* Number of current processes */
-       unsigned short pad;             /* explicit padding for m68k */
-       unsigned long totalhigh;        /* Total high memory size */
-       unsigned long freehigh;         /* Available high memory size */
-       unsigned int mem_unit;          /* Memory unit size in bytes */
-       char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
-};
-
 #endif
index 68e67e50d028e95681f37e47ba98d2e047b01b8b..6c322a90b92f8439886a954b37d58f62f29abb43 100644 (file)
@@ -162,6 +162,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_INTERNAL_ERROR   17
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL      19
+#define KVM_EXIT_S390_UCONTROL   20
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -249,6 +250,11 @@ struct kvm_run {
 #define KVM_S390_RESET_CPU_INIT  8
 #define KVM_S390_RESET_IPL       16
                __u64 s390_reset_flags;
+               /* KVM_EXIT_S390_UCONTROL */
+               struct {
+                       __u64 trans_exc_code;
+                       __u32 pgm_code;
+               } s390_ucontrol;
                /* KVM_EXIT_DCR */
                struct {
                        __u32 dcrn;
@@ -273,6 +279,20 @@ struct kvm_run {
                /* Fix the size of the union. */
                char padding[256];
        };
+
+       /*
+        * shared registers between kvm and userspace.
+        * kvm_valid_regs specifies the register classes set by the host
+        * kvm_dirty_regs specified the register classes dirtied by userspace
+        * struct kvm_sync_regs is architecture specific, as well as the
+        * bits for kvm_valid_regs and kvm_dirty_regs
+        */
+       __u64 kvm_valid_regs;
+       __u64 kvm_dirty_regs;
+       union {
+               struct kvm_sync_regs regs;
+               char padding[1024];
+       } s;
 };
 
 /* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
@@ -431,6 +451,11 @@ struct kvm_ppc_pvinfo {
 
 #define KVMIO 0xAE
 
+/* machine type bits, to be used as argument to KVM_CREATE_VM */
+#define KVM_VM_S390_UCONTROL   1
+
+#define KVM_S390_SIE_PAGE_OFFSET 1
+
 /*
  * ioctls for /dev/kvm fds:
  */
@@ -555,9 +580,15 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_PPC_SMT 64
 #define KVM_CAP_PPC_RMA        65
 #define KVM_CAP_MAX_VCPUS 66       /* returns max vcpus per vm */
+#define KVM_CAP_PPC_HIOR 67
 #define KVM_CAP_PPC_PAPR 68
+#define KVM_CAP_SW_TLB 69
+#define KVM_CAP_ONE_REG 70
 #define KVM_CAP_S390_GMAP 71
 #define KVM_CAP_TSC_DEADLINE_TIMER 72
+#define KVM_CAP_S390_UCONTROL 73
+#define KVM_CAP_SYNC_REGS 74
+#define KVM_CAP_PCI_2_3 75
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -637,6 +668,52 @@ struct kvm_clock_data {
        __u32 pad[9];
 };
 
+#define KVM_MMU_FSL_BOOKE_NOHV         0
+#define KVM_MMU_FSL_BOOKE_HV           1
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+/* Available with KVM_CAP_ONE_REG */
+
+#define KVM_REG_ARCH_MASK      0xff00000000000000ULL
+#define KVM_REG_GENERIC                0x0000000000000000ULL
+
+/*
+ * Architecture specific registers are to be defined in arch headers and
+ * ORed with the arch identifier.
+ */
+#define KVM_REG_PPC            0x1000000000000000ULL
+#define KVM_REG_X86            0x2000000000000000ULL
+#define KVM_REG_IA64           0x3000000000000000ULL
+#define KVM_REG_ARM            0x4000000000000000ULL
+#define KVM_REG_S390           0x5000000000000000ULL
+
+#define KVM_REG_SIZE_SHIFT     52
+#define KVM_REG_SIZE_MASK      0x00f0000000000000ULL
+#define KVM_REG_SIZE_U8                0x0000000000000000ULL
+#define KVM_REG_SIZE_U16       0x0010000000000000ULL
+#define KVM_REG_SIZE_U32       0x0020000000000000ULL
+#define KVM_REG_SIZE_U64       0x0030000000000000ULL
+#define KVM_REG_SIZE_U128      0x0040000000000000ULL
+#define KVM_REG_SIZE_U256      0x0050000000000000ULL
+#define KVM_REG_SIZE_U512      0x0060000000000000ULL
+#define KVM_REG_SIZE_U1024     0x0070000000000000ULL
+
+struct kvm_one_reg {
+       __u64 id;
+       __u64 addr;
+};
+
 /*
  * ioctls for VM fds
  */
@@ -655,6 +732,17 @@ struct kvm_clock_data {
                                        struct kvm_userspace_memory_region)
 #define KVM_SET_TSS_ADDR          _IO(KVMIO,   0x47)
 #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO,  0x48, __u64)
+
+/* enable ucontrol for s390 */
+struct kvm_s390_ucas_mapping {
+       __u64 user_addr;
+       __u64 vcpu_addr;
+       __u64 length;
+};
+#define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
+#define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
+#define KVM_S390_VCPU_FAULT     _IOW(KVMIO, 0x52, unsigned long)
+
 /* Device model IOC */
 #define KVM_CREATE_IRQCHIP        _IO(KVMIO,   0x60)
 #define KVM_IRQ_LINE              _IOW(KVMIO,  0x61, struct kvm_irq_level)
@@ -697,6 +785,9 @@ struct kvm_clock_data {
 /* Available with KVM_CAP_TSC_CONTROL */
 #define KVM_SET_TSC_KHZ           _IO(KVMIO,  0xa2)
 #define KVM_GET_TSC_KHZ           _IO(KVMIO,  0xa3)
+/* Available with KVM_CAP_PCI_2_3 */
+#define KVM_ASSIGN_SET_INTX_MASK  _IOW(KVMIO,  0xa4, \
+                                      struct kvm_assigned_pci_dev)
 
 /*
  * ioctls for vcpu fds
@@ -763,8 +854,15 @@ struct kvm_clock_data {
 #define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
 /* Available with KVM_CAP_RMA */
 #define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_SW_TLB */
+#define KVM_DIRTY_TLB            _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
+/* Available with KVM_CAP_ONE_REG */
+#define KVM_GET_ONE_REG                  _IOW(KVMIO,  0xab, struct kvm_one_reg)
+#define KVM_SET_ONE_REG                  _IOW(KVMIO,  0xac, struct kvm_one_reg)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
+#define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
+#define KVM_DEV_ASSIGN_MASK_INTX       (1 << 2)
 
 struct kvm_assigned_pci_dev {
        __u32 assigned_dev_id;
index ca1b153585d3e6e2196f5d5c147d965c6bd84f14..665a260c7e09948fa3b5e3516efca2890edef840 100644 (file)
@@ -172,11 +172,6 @@ static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
  */
 #define KVM_MEM_MAX_NR_PAGES ((1UL << 31) - 1)
 
-struct kvm_lpage_info {
-       unsigned long rmap_pde;
-       int write_count;
-};
-
 struct kvm_memory_slot {
        gfn_t base_gfn;
        unsigned long npages;
@@ -185,7 +180,7 @@ struct kvm_memory_slot {
        unsigned long *dirty_bitmap;
        unsigned long *dirty_bitmap_head;
        unsigned long nr_dirty_pages;
-       struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
+       struct kvm_arch_memory_slot arch;
        unsigned long userspace_addr;
        int user_alloc;
        int id;
@@ -377,6 +372,9 @@ int kvm_set_memory_region(struct kvm *kvm,
 int __kvm_set_memory_region(struct kvm *kvm,
                            struct kvm_userspace_memory_region *mem,
                            int user_alloc);
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont);
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages);
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                struct kvm_memory_slot *memslot,
                                struct kvm_memory_slot old,
@@ -386,6 +384,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                                struct kvm_userspace_memory_region *mem,
                                struct kvm_memory_slot old,
                                int user_alloc);
+bool kvm_largepages_enabled(void);
 void kvm_disable_largepages(void);
 void kvm_arch_flush_shadow(struct kvm *kvm);
 
@@ -451,6 +450,7 @@ long kvm_arch_dev_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg);
 long kvm_arch_vcpu_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg);
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
 
 int kvm_dev_ioctl_check_extension(long ext);
 
@@ -521,7 +521,7 @@ static inline void kvm_arch_free_vm(struct kvm *kvm)
 }
 #endif
 
-int kvm_arch_init_vm(struct kvm *kvm);
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
 void kvm_arch_destroy_vm(struct kvm *kvm);
 void kvm_free_all_assigned_devices(struct kvm *kvm);
 void kvm_arch_sync_events(struct kvm *kvm);
@@ -547,6 +547,7 @@ struct kvm_assigned_dev_kernel {
        unsigned int entries_nr;
        int host_irq;
        bool host_irq_disabled;
+       bool pci_2_3;
        struct msix_entry *host_msix_entries;
        int guest_irq;
        struct msix_entry *guest_msix_entries;
@@ -556,6 +557,7 @@ struct kvm_assigned_dev_kernel {
        struct pci_dev *dev;
        struct kvm *kvm;
        spinlock_t intx_lock;
+       spinlock_t intx_mask_lock;
        char irq_name[32];
        struct pci_saved_state *pci_saved_state;
 };
@@ -651,11 +653,43 @@ static inline void kvm_guest_exit(void)
        current->flags &= ~PF_VCPU;
 }
 
+/*
+ * search_memslots() and __gfn_to_memslot() are here because they are
+ * used in non-modular code in arch/powerpc/kvm/book3s_hv_rm_mmu.c.
+ * gfn_to_memslot() itself isn't here as an inline because that would
+ * bloat other code too much.
+ */
+static inline struct kvm_memory_slot *
+search_memslots(struct kvm_memslots *slots, gfn_t gfn)
+{
+       struct kvm_memory_slot *memslot;
+
+       kvm_for_each_memslot(memslot, slots)
+               if (gfn >= memslot->base_gfn &&
+                     gfn < memslot->base_gfn + memslot->npages)
+                       return memslot;
+
+       return NULL;
+}
+
+static inline struct kvm_memory_slot *
+__gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn)
+{
+       return search_memslots(slots, gfn);
+}
+
 static inline int memslot_id(struct kvm *kvm, gfn_t gfn)
 {
        return gfn_to_memslot(kvm, gfn)->id;
 }
 
+static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level)
+{
+       /* KVM_HPAGE_GFN_SHIFT(PT_PAGE_TABLE_LEVEL) must be 0. */
+       return (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
+               (base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
+}
+
 static inline unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot,
                                               gfn_t gfn)
 {
@@ -702,12 +736,16 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se
        if (unlikely(vcpu->kvm->mmu_notifier_count))
                return 1;
        /*
-        * Both reads happen under the mmu_lock and both values are
-        * modified under mmu_lock, so there's no need of smb_rmb()
-        * here in between, otherwise mmu_notifier_count should be
-        * read before mmu_notifier_seq, see
-        * mmu_notifier_invalidate_range_end write side.
+        * Ensure the read of mmu_notifier_count happens before the read
+        * of mmu_notifier_seq.  This interacts with the smp_wmb() in
+        * mmu_notifier_invalidate_range_end to make sure that the caller
+        * either sees the old (non-zero) value of mmu_notifier_count or
+        * the new (incremented) value of mmu_notifier_seq.
+        * PowerPC Book3s HV KVM calls this under a per-page lock
+        * rather than under kvm->mmu_lock, for scalability, so
+        * can't rely on kvm->mmu_lock to keep things ordered.
         */
+       smp_rmb();
        if (vcpu->kvm->mmu_notifier_seq != mmu_seq)
                return 1;
        return 0;
@@ -770,6 +808,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
 {
        return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
 }
+
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
+
+#else
+
+static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
+
 #endif
 
 #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
index 801b44b07aac9ed2738d7efcbce164ea349adef6..a5199f6d0e82592dde0e4ba7908b1d1b70323483 100644 (file)
@@ -56,8 +56,7 @@
  */
 
 #include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/processor.h>
+#include <asm/cmpxchg.h>
 
 struct llist_head {
        struct llist_node *first;
index 88e78dedc2e81394f7cbe2e9094782fc2ce32ba5..eab507f2b1cb649484f9e96028b51c7cce737e12 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/path.h>
 #include <linux/key.h>
 #include <linux/skbuff.h>
-#include <asm/system.h>
 
 
 /* Auxiliary data to use in generating the audit record. */
index 92be3476c9f5560d8623ac5cae738e1471525f22..84d071ade1d89df5dd9faf6e6de1c7f3a0f88bcf 100644 (file)
@@ -263,6 +263,22 @@ enum {
 #define PM8607_PD_PREBIAS_MASK         (0x1F << 0)
 #define PM8607_PD_PRECHG_MASK          (7 << 5)
 
+#define PM8606_REF_GP_OSC_OFF         0
+#define PM8606_REF_GP_OSC_ON          1
+#define PM8606_REF_GP_OSC_UNKNOWN     2
+
+/* Clients of reference group and 8MHz oscillator in 88PM8606 */
+enum pm8606_ref_gp_and_osc_clients {
+       REF_GP_NO_CLIENTS       = 0,
+       WLED1_DUTY              = (1<<0), /*PF 0x02.7:0*/
+       WLED2_DUTY              = (1<<1), /*PF 0x04.7:0*/
+       WLED3_DUTY              = (1<<2), /*PF 0x06.7:0*/
+       RGB1_ENABLE             = (1<<3), /*PF 0x07.1*/
+       RGB2_ENABLE             = (1<<4), /*PF 0x07.2*/
+       LDO_VBR_EN              = (1<<5), /*PF 0x12.0*/
+       REF_GP_MAX_CLIENT       = 0xFFFF
+};
+
 /* Interrupt Number in 88PM8607 */
 enum {
        PM8607_IRQ_ONKEY,
@@ -298,6 +314,7 @@ enum {
 struct pm860x_chip {
        struct device           *dev;
        struct mutex            irq_lock;
+       struct mutex            osc_lock;
        struct i2c_client       *client;
        struct i2c_client       *companion;     /* companion chip client */
        struct regmap           *regmap;
@@ -305,12 +322,15 @@ struct pm860x_chip {
 
        int                     buck3_double;   /* DVC ramp slope double */
        unsigned short          companion_addr;
+       unsigned short          osc_vote;
        int                     id;
        int                     irq_mode;
        int                     irq_base;
        int                     core_irq;
        unsigned char           chip_version;
+       unsigned char           osc_status;
 
+       unsigned int            wakeup_flag;
 };
 
 enum {
@@ -369,6 +389,9 @@ struct pm860x_platform_data {
        int             num_regulators;
 };
 
+extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short);
+extern int pm8606_osc_disable(struct pm860x_chip *, unsigned short);
+
 extern int pm860x_reg_read(struct i2c_client *, int);
 extern int pm860x_reg_write(struct i2c_client *, int, unsigned char);
 extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
index e20dd6ead1d09f2dee7d35af32397f40ad92d8f4..5fa697477b71fa6d6fe14fecf3f679bb22851b9a 100644 (file)
@@ -34,13 +34,6 @@ struct device;
 #define AB5500_1_1     0x21
 #define AB5500_2_0     0x24
 
-/* AB8500 CIDs*/
-#define AB8500_CUT1P0  0x10
-#define AB8500_CUT1P1  0x11
-#define AB8500_CUT2P0  0x20
-#define AB8500_CUT3P0  0x30
-#define AB8500_CUT3P3  0x33
-
 /*
  * AB3100, EVENTA1, A2 and A3 event register flags
  * these are catenated into a single 32-bit flag in the code
index 488a8c920a29c30e23ba51134eedf94207205b39..2387c207ea86d5cc2cf5df7e8aa20e90c3ae2301 100644 (file)
 
 /*
  * Platform data to register a block: only the initial gpio/irq number.
+ * Array sizes are large enough to contain all AB8500 and AB9540 GPIO
+ * registers.
  */
 
 struct ab8500_gpio_platform_data {
        int gpio_base;
        u32 irq_base;
-       u8  config_reg[7];
+       u8  config_reg[8];
 };
 
 #endif /* _AB8500_GPIO_H */
index 10da0291f8f8505de74971003a5c697f2865228f..10eb50973c393dbd9a75ef8c6e214670e7c0785b 100644 (file)
@@ -71,6 +71,13 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
 #define AB8500_SWATCTRL                        0x230
 #define AB8500_HIQCLKCTRL              0x232
 #define AB8500_VSIMSYSCLKCTRL          0x233
+#define AB9540_SYSCLK12BUFCTRL         0x234
+#define AB9540_SYSCLK12CONFCTRL                0x235
+#define AB9540_SYSCLK12BUFCTRL2                0x236
+#define AB9540_SYSCLK12BUF1VALID       0x237
+#define AB9540_SYSCLK12BUF2VALID       0x238
+#define AB9540_SYSCLK12BUF3VALID       0x239
+#define AB9540_SYSCLK12BUF4VALID       0x23A
 
 /* Bits */
 #define AB8500_TURNONSTATUS_PORNVBAT BIT(0)
@@ -251,4 +258,40 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
 #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ7VALID BIT(6)
 #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ8VALID BIT(7)
 
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF1ENA BIT(0)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF2ENA BIT(1)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF3ENA BIT(2)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF4ENA BIT(3)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUFENA_MASK 0x0F
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF1STRE BIT(4)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF2STRE BIT(5)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF3STRE BIT(6)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF4STRE BIT(7)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUFSTRE_MASK 0xF0
+
+#define AB9540_SYSCLK12CONFCTRL_PLL26TO38ENA BIT(0)
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK12USBMUXSEL BIT(1)
+#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_MASK 0x0C
+#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_SHIFT 2
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK12BUFMUX BIT(4)
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK12PLLMUX BIT(5)
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK2MUXVALID BIT(6)
+
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF1PDENA BIT(0)
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF2PDENA BIT(1)
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF3PDENA BIT(2)
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF4PDENA BIT(3)
+
+#define AB9540_SYSCLK12BUF1VALID_SYSCLK12BUF1VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF1VALID_SYSCLK12BUF1VALID_SHIFT 0
+
+#define AB9540_SYSCLK12BUF2VALID_SYSCLK12BUF2VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF2VALID_SYSCLK12BUF2VALID_SHIFT 0
+
+#define AB9540_SYSCLK12BUF3VALID_SYSCLK12BUF3VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF3VALID_SYSCLK12BUF3VALID_SHIFT 0
+
+#define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0
+
 #endif /* __AB8500_SYSCTRL_H */
index dca94396190d19a243dfc4d1ddc60b9f9b6fc896..fccc3002f271de0e3d7e46cf7ce2525794176b2b 100644 (file)
 
 struct device;
 
+/*
+ * AB IC versions
+ *
+ * AB8500_VERSION_AB8500 should be 0xFF but will never be read as need a
+ * non-supported multi-byte I2C access via PRCMU. Set to 0x00 to ease the
+ * print of version string.
+ */
+enum ab8500_version {
+       AB8500_VERSION_AB8500 = 0x0,
+       AB8500_VERSION_AB8505 = 0x1,
+       AB8500_VERSION_AB9540 = 0x2,
+       AB8500_VERSION_AB8540 = 0x3,
+       AB8500_VERSION_UNDEFINED,
+};
+
+/* AB8500 CIDs*/
+#define AB8500_CUTEARLY        0x00
+#define AB8500_CUT1P0  0x10
+#define AB8500_CUT1P1  0x11
+#define AB8500_CUT2P0  0x20
+#define AB8500_CUT3P0  0x30
+#define AB8500_CUT3P3  0x33
+
 /*
  * AB8500 bank addresses
  */
@@ -37,30 +60,34 @@ struct device;
 
 /*
  * Interrupts
+ * Values used to index into array ab8500_irq_regoffset[] defined in
+ * drivers/mdf/ab8500-core.c
  */
-
-#define AB8500_INT_MAIN_EXT_CH_NOT_OK  0
-#define AB8500_INT_UN_PLUG_TV_DET      1
-#define AB8500_INT_PLUG_TV_DET         2
+/* Definitions for AB8500 and AB9540 */
+/* ab8500_irq_regoffset[0] -> IT[Source|Latch|Mask]1 */
+#define AB8500_INT_MAIN_EXT_CH_NOT_OK  0 /* not 8505/9540 */
+#define AB8500_INT_UN_PLUG_TV_DET      1 /* not 8505/9540 */
+#define AB8500_INT_PLUG_TV_DET         2 /* not 8505/9540 */
 #define AB8500_INT_TEMP_WARM           3
 #define AB8500_INT_PON_KEY2DB_F                4
 #define AB8500_INT_PON_KEY2DB_R                5
 #define AB8500_INT_PON_KEY1DB_F                6
 #define AB8500_INT_PON_KEY1DB_R                7
+/* ab8500_irq_regoffset[1] -> IT[Source|Latch|Mask]2 */
 #define AB8500_INT_BATT_OVV            8
-#define AB8500_INT_MAIN_CH_UNPLUG_DET  10
-#define AB8500_INT_MAIN_CH_PLUG_DET    11
-#define AB8500_INT_USB_ID_DET_F                12
-#define AB8500_INT_USB_ID_DET_R                13
+#define AB8500_INT_MAIN_CH_UNPLUG_DET  10 /* not 8505 */
+#define AB8500_INT_MAIN_CH_PLUG_DET    11 /* not 8505 */
 #define AB8500_INT_VBUS_DET_F          14
 #define AB8500_INT_VBUS_DET_R          15
+/* ab8500_irq_regoffset[2] -> IT[Source|Latch|Mask]3 */
 #define AB8500_INT_VBUS_CH_DROP_END    16
 #define AB8500_INT_RTC_60S             17
 #define AB8500_INT_RTC_ALARM           18
 #define AB8500_INT_BAT_CTRL_INDB       20
 #define AB8500_INT_CH_WD_EXP           21
 #define AB8500_INT_VBUS_OVV            22
-#define AB8500_INT_MAIN_CH_DROP_END    23
+#define AB8500_INT_MAIN_CH_DROP_END    23 /* not 8505/9540 */
+/* ab8500_irq_regoffset[3] -> IT[Source|Latch|Mask]4 */
 #define AB8500_INT_CCN_CONV_ACC                24
 #define AB8500_INT_INT_AUD             25
 #define AB8500_INT_CCEOC               26
@@ -69,7 +96,8 @@ struct device;
 #define AB8500_INT_LOW_BAT_R           29
 #define AB8500_INT_BUP_CHG_NOT_OK      30
 #define AB8500_INT_BUP_CHG_OK          31
-#define AB8500_INT_GP_HW_ADC_CONV_END  32
+/* ab8500_irq_regoffset[4] -> IT[Source|Latch|Mask]5 */
+#define AB8500_INT_GP_HW_ADC_CONV_END  32 /* not 8505 */
 #define AB8500_INT_ACC_DETECT_1DB_F    33
 #define AB8500_INT_ACC_DETECT_1DB_R    34
 #define AB8500_INT_ACC_DETECT_22DB_F   35
@@ -77,38 +105,43 @@ struct device;
 #define AB8500_INT_ACC_DETECT_21DB_F   37
 #define AB8500_INT_ACC_DETECT_21DB_R   38
 #define AB8500_INT_GP_SW_ADC_CONV_END  39
-#define AB8500_INT_GPIO6R              40
-#define AB8500_INT_GPIO7R              41
-#define AB8500_INT_GPIO8R              42
-#define AB8500_INT_GPIO9R              43
+/* ab8500_irq_regoffset[5] -> IT[Source|Latch|Mask]7 */
+#define AB8500_INT_GPIO6R              40 /* not 8505/9540 */
+#define AB8500_INT_GPIO7R              41 /* not 8505/9540 */
+#define AB8500_INT_GPIO8R              42 /* not 8505/9540 */
+#define AB8500_INT_GPIO9R              43 /* not 8505/9540 */
 #define AB8500_INT_GPIO10R             44
 #define AB8500_INT_GPIO11R             45
-#define AB8500_INT_GPIO12R             46
+#define AB8500_INT_GPIO12R             46 /* not 8505 */
 #define AB8500_INT_GPIO13R             47
-#define AB8500_INT_GPIO24R             48
-#define AB8500_INT_GPIO25R             49
-#define AB8500_INT_GPIO36R             50
-#define AB8500_INT_GPIO37R             51
-#define AB8500_INT_GPIO38R             52
-#define AB8500_INT_GPIO39R             53
+/* ab8500_irq_regoffset[6] -> IT[Source|Latch|Mask]8 */
+#define AB8500_INT_GPIO24R             48 /* not 8505 */
+#define AB8500_INT_GPIO25R             49 /* not 8505 */
+#define AB8500_INT_GPIO36R             50 /* not 8505/9540 */
+#define AB8500_INT_GPIO37R             51 /* not 8505/9540 */
+#define AB8500_INT_GPIO38R             52 /* not 8505/9540 */
+#define AB8500_INT_GPIO39R             53 /* not 8505/9540 */
 #define AB8500_INT_GPIO40R             54
 #define AB8500_INT_GPIO41R             55
-#define AB8500_INT_GPIO6F              56
-#define AB8500_INT_GPIO7F              57
-#define AB8500_INT_GPIO8F              58
-#define AB8500_INT_GPIO9F              59
+/* ab8500_irq_regoffset[7] -> IT[Source|Latch|Mask]9 */
+#define AB8500_INT_GPIO6F              56 /* not 8505/9540 */
+#define AB8500_INT_GPIO7F              57 /* not 8505/9540 */
+#define AB8500_INT_GPIO8F              58 /* not 8505/9540 */
+#define AB8500_INT_GPIO9F              59 /* not 8505/9540 */
 #define AB8500_INT_GPIO10F             60
 #define AB8500_INT_GPIO11F             61
-#define AB8500_INT_GPIO12F             62
+#define AB8500_INT_GPIO12F             62 /* not 8505 */
 #define AB8500_INT_GPIO13F             63
-#define AB8500_INT_GPIO24F             64
-#define AB8500_INT_GPIO25F             65
-#define AB8500_INT_GPIO36F             66
-#define AB8500_INT_GPIO37F             67
-#define AB8500_INT_GPIO38F             68
-#define AB8500_INT_GPIO39F             69
+/* ab8500_irq_regoffset[8] -> IT[Source|Latch|Mask]10 */
+#define AB8500_INT_GPIO24F             64 /* not 8505 */
+#define AB8500_INT_GPIO25F             65 /* not 8505 */
+#define AB8500_INT_GPIO36F             66 /* not 8505/9540 */
+#define AB8500_INT_GPIO37F             67 /* not 8505/9540 */
+#define AB8500_INT_GPIO38F             68 /* not 8505/9540 */
+#define AB8500_INT_GPIO39F             69 /* not 8505/9540 */
 #define AB8500_INT_GPIO40F             70
 #define AB8500_INT_GPIO41F             71
+/* ab8500_irq_regoffset[9] -> IT[Source|Latch|Mask]12 */
 #define AB8500_INT_ADP_SOURCE_ERROR    72
 #define AB8500_INT_ADP_SINK_ERROR      73
 #define AB8500_INT_ADP_PROBE_PLUG      74
@@ -116,30 +149,67 @@ struct device;
 #define AB8500_INT_ADP_SENSE_OFF       76
 #define AB8500_INT_USB_PHY_POWER_ERR   78
 #define AB8500_INT_USB_LINK_STATUS     79
+/* ab8500_irq_regoffset[10] -> IT[Source|Latch|Mask]19 */
 #define AB8500_INT_BTEMP_LOW           80
 #define AB8500_INT_BTEMP_LOW_MEDIUM    81
 #define AB8500_INT_BTEMP_MEDIUM_HIGH   82
 #define AB8500_INT_BTEMP_HIGH          83
-#define AB8500_INT_USB_CHARGER_NOT_OK  89
+/* ab8500_irq_regoffset[11] -> IT[Source|Latch|Mask]20 */
+#define AB8500_INT_SRP_DETECT          88
+#define AB8500_INT_USB_CHARGER_NOT_OKR 89
 #define AB8500_INT_ID_WAKEUP_R         90
 #define AB8500_INT_ID_DET_R1R          92
 #define AB8500_INT_ID_DET_R2R          93
 #define AB8500_INT_ID_DET_R3R          94
 #define AB8500_INT_ID_DET_R4R          95
+/* ab8500_irq_regoffset[12] -> IT[Source|Latch|Mask]21 */
 #define AB8500_INT_ID_WAKEUP_F         96
 #define AB8500_INT_ID_DET_R1F          98
 #define AB8500_INT_ID_DET_R2F          99
 #define AB8500_INT_ID_DET_R3F          100
 #define AB8500_INT_ID_DET_R4F          101
-#define AB8500_INT_USB_CHG_DET_DONE    102
+#define AB8500_INT_CHAUTORESTARTAFTSEC  102
+#define AB8500_INT_CHSTOPBYSEC         103
+/* ab8500_irq_regoffset[13] -> IT[Source|Latch|Mask]22 */
 #define AB8500_INT_USB_CH_TH_PROT_F    104
 #define AB8500_INT_USB_CH_TH_PROT_R    105
-#define AB8500_INT_MAIN_CH_TH_PROT_F   106
-#define AB8500_INT_MAIN_CH_TH_PROT_R   107
-#define AB8500_INT_USB_CHARGER_NOT_OKF 111
+#define AB8500_INT_MAIN_CH_TH_PROT_F   106 /* not 8505/9540 */
+#define AB8500_INT_MAIN_CH_TH_PROT_R   107 /* not 8505/9540 */
+#define AB8500_INT_CHCURLIMNOHSCHIRP   109
+#define AB8500_INT_CHCURLIMHSCHIRP     110
+#define AB8500_INT_XTAL32K_KO          111
+
+/* Definitions for AB9540 */
+/* ab8500_irq_regoffset[14] -> IT[Source|Latch|Mask]13 */
+#define AB9540_INT_GPIO50R             113
+#define AB9540_INT_GPIO51R             114 /* not 8505 */
+#define AB9540_INT_GPIO52R             115
+#define AB9540_INT_GPIO53R             116
+#define AB9540_INT_GPIO54R             117 /* not 8505 */
+#define AB9540_INT_IEXT_CH_RF_BFN_R    118
+#define AB9540_INT_IEXT_CH_RF_BFN_F    119
+/* ab8500_irq_regoffset[15] -> IT[Source|Latch|Mask]14 */
+#define AB9540_INT_GPIO50F             121
+#define AB9540_INT_GPIO51F             122 /* not 8505 */
+#define AB9540_INT_GPIO52F             123
+#define AB9540_INT_GPIO53F             124
+#define AB9540_INT_GPIO54F             125 /* not 8505 */
 
+/*
+ * AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the
+ * entire platform. This is a "compile time" constant so this must be set to
+ * the largest possible value that may be encountered with different AB SOCs.
+ * Of the currently supported AB devices, AB8500 and AB9540, it is the AB9540
+ * which is larger.
+ */
 #define AB8500_NR_IRQS                 112
+#define AB8505_NR_IRQS                 128
+#define AB9540_NR_IRQS                 128
+/* This is set to the roof of any AB8500 chip variant IRQ counts */
+#define AB8500_MAX_NR_IRQS             AB9540_NR_IRQS
+
 #define AB8500_NUM_IRQ_REGS            14
+#define AB9540_NUM_IRQ_REGS            17
 
 /**
  * struct ab8500 - ab8500 internal structure
@@ -147,13 +217,18 @@ struct device;
  * @lock: read/write operations lock
  * @irq_lock: genirq bus lock
  * @irq: irq line
+ * @version: chip version id (e.g. ab8500 or ab9540)
  * @chip_id: chip revision id
  * @write: register write
+ * @write_masked: masked register write
  * @read: register read
  * @rx_buf: rx buf for SPI
  * @tx_buf: tx buf for SPI
  * @mask: cache of IRQ regs for bus lock
  * @oldmask: cache of previous IRQ regs for bus lock
+ * @mask_size: Actual number of valid entries in mask[], oldmask[] and
+ * irq_reg_offset
+ * @irq_reg_offset: Array of offsets into IRQ registers
  */
 struct ab8500 {
        struct device   *dev;
@@ -162,16 +237,20 @@ struct ab8500 {
 
        int             irq_base;
        int             irq;
+       enum ab8500_version version;
        u8              chip_id;
 
-       int (*write) (struct ab8500 *a8500, u16 addr, u8 data);
-       int (*read) (struct ab8500 *a8500, u16 addr);
+       int (*write)(struct ab8500 *ab8500, u16 addr, u8 data);
+       int (*write_masked)(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data);
+       int (*read)(struct ab8500 *ab8500, u16 addr);
 
        unsigned long   tx_buf[4];
        unsigned long   rx_buf[4];
 
-       u8 mask[AB8500_NUM_IRQ_REGS];
-       u8 oldmask[AB8500_NUM_IRQ_REGS];
+       u8 *mask;
+       u8 *oldmask;
+       int mask_size;
+       const int *irq_reg_offset;
 };
 
 struct regulator_reg_init;
@@ -197,7 +276,52 @@ struct ab8500_platform_data {
        struct ab8500_gpio_platform_data *gpio;
 };
 
-extern int __devinit ab8500_init(struct ab8500 *ab8500);
+extern int __devinit ab8500_init(struct ab8500 *ab8500,
+                                enum ab8500_version version);
 extern int __devexit ab8500_exit(struct ab8500 *ab8500);
 
+static inline int is_ab8500(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB8500;
+}
+
+static inline int is_ab8505(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB8505;
+}
+
+static inline int is_ab9540(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB9540;
+}
+
+static inline int is_ab8540(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB8540;
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_1p0_or_earlier(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P0));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_1p1_or_earlier(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P1));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_2p0_or_earlier(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT2P0));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_2p0(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
+}
+
 #endif /* MFD_AB8500_H */
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
new file mode 100644 (file)
index 0000000..22c1007
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * anatop.h - Anatop MFD driver
+ *
+ *  Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ *  Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __LINUX_MFD_ANATOP_H
+#define __LINUX_MFD_ANATOP_H
+
+#include <linux/spinlock.h>
+
+/**
+ * anatop - MFD data
+ * @ioreg: ioremap register
+ * @reglock: spinlock for register read/write
+ */
+struct anatop {
+       void *ioreg;
+       spinlock_t reglock;
+};
+
+extern u32 anatop_get_bits(struct anatop *, u32, int, int);
+extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
+
+#endif /*  __LINUX_MFD_ANATOP_H */
index 5702d1be13b41ceea2ce9761ec6dbc41d75da723..7ffbd6e9e7fc00f428c4c036fe53443cbcc3e80f 100644 (file)
@@ -76,8 +76,6 @@ enum da9052_chip_id {
 struct da9052_pdata;
 
 struct da9052 {
-       struct mutex io_lock;
-
        struct device *dev;
        struct regmap *regmap;
 
index 60d27f7bfc1f761d915a9635a3c275155b7577d3..b3a43b1263fead2092a4bffd7b87d878e5c0cbb5 100644 (file)
 #define __MFD_DB8500_PRCMU_H
 
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+/*
+ * Registers
+ */
+#define DB8500_PRCM_GPIOCR 0x138
+#define DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0    BIT(0)
+#define DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD     BIT(9)
+#define DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1    BIT(11)
+#define DB8500_PRCM_GPIOCR_SPI2_SELECT         BIT(23)
+
+#define DB8500_PRCM_LINE_VALUE 0x170
+#define DB8500_PRCM_LINE_VALUE_HSI_CAWAKE0     BIT(3)
+
+#define DB8500_PRCM_DSI_SW_RESET 0x324
+#define DB8500_PRCM_DSI_SW_RESET_DSI0_SW_RESETN BIT(0)
+#define DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1)
+#define DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2)
 
 /* This portion previously known as <mach/prcmu-fw-defs_v1.h> */
 
@@ -421,40 +439,22 @@ enum auto_enable {
 /* End of file previously known as prcmu-fw-defs_v1.h */
 
 /**
- * enum hw_acc_dev - enum for hw accelerators
- * @HW_ACC_SVAMMDSP: for SVAMMDSP
- * @HW_ACC_SVAPIPE:  for SVAPIPE
- * @HW_ACC_SIAMMDSP: for SIAMMDSP
- * @HW_ACC_SIAPIPE: for SIAPIPE
- * @HW_ACC_SGA: for SGA
- * @HW_ACC_B2R2: for B2R2
- * @HW_ACC_MCDE: for MCDE
- * @HW_ACC_ESRAM1: for ESRAM1
- * @HW_ACC_ESRAM2: for ESRAM2
- * @HW_ACC_ESRAM3: for ESRAM3
- * @HW_ACC_ESRAM4: for ESRAM4
- * @NUM_HW_ACC: number of hardware accelerators
- *
- * Different hw accelerators which can be turned ON/
- * OFF or put into retention (MMDSPs and ESRAMs).
- * Used with EPOD API.
+ * enum prcmu_power_status - results from set_power_state
+ * @PRCMU_SLEEP_OK: Sleep went ok
+ * @PRCMU_DEEP_SLEEP_OK: DeepSleep went ok
+ * @PRCMU_IDLE_OK: Idle went ok
+ * @PRCMU_DEEPIDLE_OK: DeepIdle went ok
+ * @PRCMU_PRCMU2ARMPENDINGIT_ER: Pending interrupt detected
+ * @PRCMU_ARMPENDINGIT_ER: Pending interrupt detected
  *
- * NOTE! Deprecated, to be removed when all users switched over to use the
- * regulator API.
  */
-enum hw_acc_dev {
-       HW_ACC_SVAMMDSP,
-       HW_ACC_SVAPIPE,
-       HW_ACC_SIAMMDSP,
-       HW_ACC_SIAPIPE,
-       HW_ACC_SGA,
-       HW_ACC_B2R2,
-       HW_ACC_MCDE,
-       HW_ACC_ESRAM1,
-       HW_ACC_ESRAM2,
-       HW_ACC_ESRAM3,
-       HW_ACC_ESRAM4,
-       NUM_HW_ACC
+enum prcmu_power_status {
+       PRCMU_SLEEP_OK                  = 0xf3,
+       PRCMU_DEEP_SLEEP_OK             = 0xf6,
+       PRCMU_IDLE_OK                   = 0xf0,
+       PRCMU_DEEPIDLE_OK               = 0xe3,
+       PRCMU_PRCMU2ARMPENDINGIT_ER     = 0x91,
+       PRCMU_ARMPENDINGIT_ER           = 0x93,
 };
 
 /*
@@ -493,6 +493,20 @@ struct prcmu_auto_pm_config {
        u8 sva_policy;
 };
 
+#define PRCMU_FW_PROJECT_U8500         2
+#define PRCMU_FW_PROJECT_U9500         4
+#define PRCMU_FW_PROJECT_U8500_C2      7
+#define PRCMU_FW_PROJECT_U9500_C2      11
+#define PRCMU_FW_PROJECT_U8520         13
+#define PRCMU_FW_PROJECT_U8420         14
+
+struct prcmu_fw_version {
+       u8 project;
+       u8 api_version;
+       u8 func_version;
+       u8 errata;
+};
+
 #ifdef CONFIG_MFD_DB8500_PRCMU
 
 void db8500_prcmu_early_init(void);
@@ -500,42 +514,41 @@ int prcmu_set_rc_a2p(enum romcode_write);
 enum romcode_read prcmu_get_rc_p2a(void);
 enum ap_pwrst prcmu_get_xp70_current_state(void);
 bool prcmu_has_arm_maxopp(void);
-bool prcmu_is_u8400(void);
-int prcmu_set_ape_opp(u8 opp);
-int prcmu_get_ape_opp(void);
+struct prcmu_fw_version *prcmu_get_fw_version(void);
 int prcmu_request_ape_opp_100_voltage(bool enable);
 int prcmu_release_usb_wakeup_state(void);
-int prcmu_set_ddr_opp(u8 opp);
-int prcmu_get_ddr_opp(void);
-/* NOTE! Use regulator framework instead */
-int prcmu_set_hwacc(u16 hw_acc_dev, u8 state);
 void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
        struct prcmu_auto_pm_config *idle);
 bool prcmu_is_auto_pm_enabled(void);
 
 int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
 int prcmu_set_clock_divider(u8 clock, u8 divider);
-int prcmu_config_hotdog(u8 threshold);
-int prcmu_config_hotmon(u8 low, u8 high);
-int prcmu_start_temp_sense(u16 cycles32k);
-int prcmu_stop_temp_sense(void);
+int db8500_prcmu_config_hotdog(u8 threshold);
+int db8500_prcmu_config_hotmon(u8 low, u8 high);
+int db8500_prcmu_start_temp_sense(u16 cycles32k);
+int db8500_prcmu_stop_temp_sense(void);
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
 
 void prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-void prcmu_modem_reset(void);
-void prcmu_enable_spi2(void);
-void prcmu_disable_spi2(void);
+void db8500_prcmu_modem_reset(void);
 
-int prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
-int prcmu_enable_a9wdog(u8 id);
-int prcmu_disable_a9wdog(u8 id);
-int prcmu_kick_a9wdog(u8 id);
-int prcmu_load_a9wdog(u8 id, u32 val);
+int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
+int db8500_prcmu_enable_a9wdog(u8 id);
+int db8500_prcmu_disable_a9wdog(u8 id);
+int db8500_prcmu_kick_a9wdog(u8 id);
+int db8500_prcmu_load_a9wdog(u8 id, u32 val);
 
 void db8500_prcmu_system_reset(u16 reset_code);
 int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
+u8 db8500_prcmu_get_power_state_result(void);
+int db8500_prcmu_gic_decouple(void);
+int db8500_prcmu_gic_recouple(void);
+int db8500_prcmu_copy_gic_settings(void);
+bool db8500_prcmu_gic_pending_irq(void);
+bool db8500_prcmu_pending_irq(void);
+bool db8500_prcmu_is_cpu_in_wfi(int cpu);
 void db8500_prcmu_enable_wakeups(u32 wakeups);
 int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
 int db8500_prcmu_request_clock(u8 clock, bool enable);
@@ -549,6 +562,14 @@ u16 db8500_prcmu_get_reset_code(void);
 bool db8500_prcmu_is_ac_wake_requested(void);
 int db8500_prcmu_set_arm_opp(u8 opp);
 int db8500_prcmu_get_arm_opp(void);
+int db8500_prcmu_set_ape_opp(u8 opp);
+int db8500_prcmu_get_ape_opp(void);
+int db8500_prcmu_set_ddr_opp(u8 opp);
+int db8500_prcmu_get_ddr_opp(void);
+
+u32 db8500_prcmu_read(unsigned int reg);
+void db8500_prcmu_write(unsigned int reg, u32 value);
+void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value);
 
 #else /* !CONFIG_MFD_DB8500_PRCMU */
 
@@ -574,17 +595,17 @@ static inline bool prcmu_has_arm_maxopp(void)
        return false;
 }
 
-static inline bool prcmu_is_u8400(void)
+static inline struct prcmu_fw_version *prcmu_get_fw_version(void)
 {
-       return false;
+       return NULL;
 }
 
-static inline int prcmu_set_ape_opp(u8 opp)
+static inline int db8500_prcmu_set_ape_opp(u8 opp)
 {
        return 0;
 }
 
-static inline int prcmu_get_ape_opp(void)
+static inline int db8500_prcmu_get_ape_opp(void)
 {
        return APE_100_OPP;
 }
@@ -599,21 +620,16 @@ static inline int prcmu_release_usb_wakeup_state(void)
        return 0;
 }
 
-static inline int prcmu_set_ddr_opp(u8 opp)
+static inline int db8500_prcmu_set_ddr_opp(u8 opp)
 {
        return 0;
 }
 
-static inline int prcmu_get_ddr_opp(void)
+static inline int db8500_prcmu_get_ddr_opp(void)
 {
        return DDR_100_OPP;
 }
 
-static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state)
-{
-       return 0;
-}
-
 static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
        struct prcmu_auto_pm_config *idle)
 {
@@ -634,22 +650,22 @@ static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
        return 0;
 }
 
-static inline int prcmu_config_hotdog(u8 threshold)
+static inline int db8500_prcmu_config_hotdog(u8 threshold)
 {
        return 0;
 }
 
-static inline int prcmu_config_hotmon(u8 low, u8 high)
+static inline int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
        return 0;
 }
 
-static inline int prcmu_start_temp_sense(u16 cycles32k)
+static inline int db8500_prcmu_start_temp_sense(u16 cycles32k)
 {
        return 0;
 }
 
-static inline int prcmu_stop_temp_sense(void)
+static inline int db8500_prcmu_stop_temp_sense(void)
 {
        return 0;
 }
@@ -668,22 +684,17 @@ static inline void prcmu_ac_wake_req(void) {}
 
 static inline void prcmu_ac_sleep_req(void) {}
 
-static inline void prcmu_modem_reset(void) {}
+static inline void db8500_prcmu_modem_reset(void) {}
 
-static inline int prcmu_enable_spi2(void)
-{
-       return 0;
-}
+static inline void db8500_prcmu_system_reset(u16 reset_code) {}
 
-static inline int prcmu_disable_spi2(void)
+static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll)
 {
        return 0;
 }
 
-static inline void db8500_prcmu_system_reset(u16 reset_code) {}
-
-static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-       bool keep_ap_pll)
+static inline u8 db8500_prcmu_get_power_state_result(void)
 {
        return 0;
 }
@@ -729,27 +740,27 @@ static inline u16 db8500_prcmu_get_reset_code(void)
        return 0;
 }
 
-static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+static inline int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 {
        return 0;
 }
 
-static inline int prcmu_enable_a9wdog(u8 id)
+static inline int db8500_prcmu_enable_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline int prcmu_disable_a9wdog(u8 id)
+static inline int db8500_prcmu_disable_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline int prcmu_kick_a9wdog(u8 id)
+static inline int db8500_prcmu_kick_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline int prcmu_load_a9wdog(u8 id, u32 val)
+static inline int db8500_prcmu_load_a9wdog(u8 id, u32 val)
 {
        return 0;
 }
@@ -769,6 +780,16 @@ static inline int db8500_prcmu_get_arm_opp(void)
        return 0;
 }
 
+static inline u32 db8500_prcmu_read(unsigned int reg)
+{
+       return 0;
+}
+
+static inline void db8500_prcmu_write(unsigned int reg, u32 value) {}
+
+static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask,
+       u32 value) {}
+
 #endif /* !CONFIG_MFD_DB8500_PRCMU */
 
 #endif /* __MFD_DB8500_PRCMU_H */
index bac942f959c18221588dd8f87620bd983282dde4..d7674eb7305f8cefc3a8396be0434ec58bd79d5d 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
-#include <asm/mach-types.h>
+#include <linux/err.h>
 
 /* PRCMU Wakeup defines */
 enum prcmu_wakeup_index {
@@ -80,6 +80,29 @@ enum prcmu_wakeup_index {
 #define EPOD_STATE_ON_CLK_OFF  0x03
 #define EPOD_STATE_ON          0x04
 
+/* DB5500 CLKOUT IDs */
+enum {
+       DB5500_CLKOUT0 = 0,
+       DB5500_CLKOUT1,
+};
+
+/* DB5500 CLKOUTx sources */
+enum {
+       DB5500_CLKOUT_REF_CLK_SEL0,
+       DB5500_CLKOUT_RTC_CLK0_SEL0,
+       DB5500_CLKOUT_ULP_CLK_SEL0,
+       DB5500_CLKOUT_STATIC0,
+       DB5500_CLKOUT_REFCLK,
+       DB5500_CLKOUT_ULPCLK,
+       DB5500_CLKOUT_ARMCLK,
+       DB5500_CLKOUT_SYSACC0CLK,
+       DB5500_CLKOUT_SOC0PLLCLK,
+       DB5500_CLKOUT_SOC1PLLCLK,
+       DB5500_CLKOUT_DDRPLLCLK,
+       DB5500_CLKOUT_TVCLK,
+       DB5500_CLKOUT_IRDACLK,
+};
+
 /*
  * CLKOUT sources
  */
@@ -111,6 +134,7 @@ enum prcmu_clock {
        PRCMU_MSP1CLK,
        PRCMU_I2CCLK,
        PRCMU_SDMMCCLK,
+       PRCMU_SPARE1CLK,
        PRCMU_SLIMCLK,
        PRCMU_PER1CLK,
        PRCMU_PER2CLK,
@@ -139,12 +163,20 @@ enum prcmu_clock {
        PRCMU_IRRCCLK,
        PRCMU_SIACLK,
        PRCMU_SVACLK,
+       PRCMU_ACLK,
        PRCMU_NUM_REG_CLOCKS,
        PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
+       PRCMU_CDCLK,
        PRCMU_TIMCLK,
        PRCMU_PLLSOC0,
        PRCMU_PLLSOC1,
        PRCMU_PLLDDR,
+       PRCMU_PLLDSI,
+       PRCMU_DSI0CLK,
+       PRCMU_DSI1CLK,
+       PRCMU_DSI0ESCCLK,
+       PRCMU_DSI1ESCCLK,
+       PRCMU_DSI2ESCCLK,
 };
 
 /**
@@ -153,12 +185,14 @@ enum prcmu_clock {
  * @APE_NO_CHANGE: The APE operating point is unchanged
  * @APE_100_OPP: The new APE operating point is ape100opp
  * @APE_50_OPP: 50%
+ * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%.
  */
 enum ape_opp {
        APE_OPP_INIT = 0x00,
        APE_NO_CHANGE = 0x01,
        APE_100_OPP = 0x02,
-       APE_50_OPP = 0x03
+       APE_50_OPP = 0x03,
+       APE_50_PARTLY_25_OPP = 0xFF,
 };
 
 /**
@@ -218,9 +252,11 @@ enum ddr_pwrst {
 
 #if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
 
+#include <mach/id.h>
+
 static inline void __init prcmu_early_init(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_early_init();
        else
                return db8500_prcmu_early_init();
@@ -229,7 +265,7 @@ static inline void __init prcmu_early_init(void)
 static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
                bool keep_ap_pll)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_set_power_state(state, keep_ulp_clk,
                        keep_ap_pll);
        else
@@ -237,9 +273,65 @@ static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
                        keep_ap_pll);
 }
 
+static inline u8 prcmu_get_power_state_result(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_power_state_result();
+}
+
+static inline int prcmu_gic_decouple(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_gic_decouple();
+}
+
+static inline int prcmu_gic_recouple(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_gic_recouple();
+}
+
+static inline bool prcmu_gic_pending_irq(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_gic_pending_irq();
+}
+
+static inline bool prcmu_is_cpu_in_wfi(int cpu)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_is_cpu_in_wfi(cpu);
+}
+
+static inline int prcmu_copy_gic_settings(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_copy_gic_settings();
+}
+
+static inline bool prcmu_pending_irq(void)
+{
+        if (cpu_is_u5500())
+                return -EINVAL;
+        else
+                return db8500_prcmu_pending_irq();
+}
+
 static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_set_epod(epod_id, epod_state);
@@ -247,7 +339,7 @@ static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
 
 static inline void prcmu_enable_wakeups(u32 wakeups)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                db5500_prcmu_enable_wakeups(wakeups);
        else
                db8500_prcmu_enable_wakeups(wakeups);
@@ -260,7 +352,7 @@ static inline void prcmu_disable_wakeups(void)
 
 static inline void prcmu_config_abb_event_readout(u32 abb_events)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                db5500_prcmu_config_abb_event_readout(abb_events);
        else
                db8500_prcmu_config_abb_event_readout(abb_events);
@@ -268,7 +360,7 @@ static inline void prcmu_config_abb_event_readout(u32 abb_events)
 
 static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                db5500_prcmu_get_abb_event_buffer(buf);
        else
                db8500_prcmu_get_abb_event_buffer(buf);
@@ -276,25 +368,40 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
 
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size);
 
 int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
 
 static inline int prcmu_request_clock(u8 clock, bool enable)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_request_clock(clock, enable);
        else
                return db8500_prcmu_request_clock(clock, enable);
 }
 
-int prcmu_set_ape_opp(u8 opp);
-int prcmu_get_ape_opp(void);
-int prcmu_set_ddr_opp(u8 opp);
-int prcmu_get_ddr_opp(void);
+unsigned long prcmu_clock_rate(u8 clock);
+long prcmu_round_clock_rate(u8 clock, unsigned long rate);
+int prcmu_set_clock_rate(u8 clock, unsigned long rate);
+
+static inline int prcmu_set_ddr_opp(u8 opp)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_set_ddr_opp(opp);
+}
+static inline int prcmu_get_ddr_opp(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_ddr_opp();
+}
 
 static inline int prcmu_set_arm_opp(u8 opp)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_set_arm_opp(opp);
@@ -302,15 +409,31 @@ static inline int prcmu_set_arm_opp(u8 opp)
 
 static inline int prcmu_get_arm_opp(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_get_arm_opp();
 }
 
+static inline int prcmu_set_ape_opp(u8 opp)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_set_ape_opp(opp);
+}
+
+static inline int prcmu_get_ape_opp(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_ape_opp();
+}
+
 static inline void prcmu_system_reset(u16 reset_code)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_system_reset(reset_code);
        else
                return db8500_prcmu_system_reset(reset_code);
@@ -318,7 +441,7 @@ static inline void prcmu_system_reset(u16 reset_code)
 
 static inline u16 prcmu_get_reset_code(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_get_reset_code();
        else
                return db8500_prcmu_get_reset_code();
@@ -326,10 +449,17 @@ static inline u16 prcmu_get_reset_code(void)
 
 void prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-void prcmu_modem_reset(void);
+static inline void prcmu_modem_reset(void)
+{
+       if (cpu_is_u5500())
+               return;
+       else
+               return db8500_prcmu_modem_reset();
+}
+
 static inline bool prcmu_is_ac_wake_requested(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_is_ac_wake_requested();
        else
                return db8500_prcmu_is_ac_wake_requested();
@@ -337,7 +467,7 @@ static inline bool prcmu_is_ac_wake_requested(void)
 
 static inline int prcmu_set_display_clocks(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_set_display_clocks();
        else
                return db8500_prcmu_set_display_clocks();
@@ -345,7 +475,7 @@ static inline int prcmu_set_display_clocks(void)
 
 static inline int prcmu_disable_dsipll(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_disable_dsipll();
        else
                return db8500_prcmu_disable_dsipll();
@@ -353,7 +483,7 @@ static inline int prcmu_disable_dsipll(void)
 
 static inline int prcmu_enable_dsipll(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_enable_dsipll();
        else
                return db8500_prcmu_enable_dsipll();
@@ -361,11 +491,107 @@ static inline int prcmu_enable_dsipll(void)
 
 static inline int prcmu_config_esram0_deep_sleep(u8 state)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_config_esram0_deep_sleep(state);
 }
+
+static inline int prcmu_config_hotdog(u8 threshold)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_hotdog(threshold);
+}
+
+static inline int prcmu_config_hotmon(u8 low, u8 high)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_hotmon(low, high);
+}
+
+static inline int prcmu_start_temp_sense(u16 cycles32k)
+{
+       if (cpu_is_u5500())
+               return  -EINVAL;
+       else
+               return  db8500_prcmu_start_temp_sense(cycles32k);
+}
+
+static inline int prcmu_stop_temp_sense(void)
+{
+       if (cpu_is_u5500())
+               return  -EINVAL;
+       else
+               return  db8500_prcmu_stop_temp_sense();
+}
+
+static inline u32 prcmu_read(unsigned int reg)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_read(reg);
+}
+
+static inline void prcmu_write(unsigned int reg, u32 value)
+{
+       if (cpu_is_u5500())
+               return;
+       else
+               db8500_prcmu_write(reg, value);
+}
+
+static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
+{
+       if (cpu_is_u5500())
+               return;
+       else
+               db8500_prcmu_write_masked(reg, mask, value);
+}
+
+static inline int prcmu_enable_a9wdog(u8 id)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_enable_a9wdog(id);
+}
+
+static inline int prcmu_disable_a9wdog(u8 id)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_disable_a9wdog(id);
+}
+
+static inline int prcmu_kick_a9wdog(u8 id)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_kick_a9wdog(id);
+}
+
+static inline int prcmu_load_a9wdog(u8 id, u32 timeout)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_load_a9wdog(id, timeout);
+}
+
+static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
+}
 #else
 
 static inline void __init prcmu_early_init(void) {}
@@ -395,6 +621,12 @@ static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        return -ENOSYS;
 }
 
+static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
+       u8 size)
+{
+       return -ENOSYS;
+}
+
 static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
 {
        return 0;
@@ -405,6 +637,21 @@ static inline int prcmu_request_clock(u8 clock, bool enable)
        return 0;
 }
 
+static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+       return 0;
+}
+
+static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
+       return 0;
+}
+
+static inline unsigned long prcmu_clock_rate(u8 clock)
+{
+       return 0;
+}
+
 static inline int prcmu_set_ape_opp(u8 opp)
 {
        return 0;
@@ -480,14 +727,133 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
        *buf = NULL;
 }
 
+static inline int prcmu_config_hotdog(u8 threshold)
+{
+       return 0;
+}
+
+static inline int prcmu_config_hotmon(u8 low, u8 high)
+{
+       return 0;
+}
+
+static inline int prcmu_start_temp_sense(u16 cycles32k)
+{
+       return 0;
+}
+
+static inline int prcmu_stop_temp_sense(void)
+{
+       return 0;
+}
+
+static inline u32 prcmu_read(unsigned int reg)
+{
+       return 0;
+}
+
+static inline void prcmu_write(unsigned int reg, u32 value) {}
+
+static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
+
+#endif
+
+static inline void prcmu_set(unsigned int reg, u32 bits)
+{
+       prcmu_write_masked(reg, bits, bits);
+}
+
+static inline void prcmu_clear(unsigned int reg, u32 bits)
+{
+       prcmu_write_masked(reg, bits, 0);
+}
+
+#if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
+
+/**
+ * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
+ */
+static inline void prcmu_enable_spi2(void)
+{
+       if (cpu_is_u8500())
+               prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
+}
+
+/**
+ * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
+ */
+static inline void prcmu_disable_spi2(void)
+{
+       if (cpu_is_u8500())
+               prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
+}
+
+/**
+ * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+static inline void prcmu_enable_stm_mod_uart(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_set(DB8500_PRCM_GPIOCR,
+                       (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
+                        DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
+       }
+}
+
+/**
+ * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+static inline void prcmu_disable_stm_mod_uart(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_clear(DB8500_PRCM_GPIOCR,
+                       (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
+                        DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
+       }
+}
+
+/**
+ * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1.
+ */
+static inline void prcmu_enable_stm_ape(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_set(DB8500_PRCM_GPIOCR,
+                       DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
+       }
+}
+
+/**
+ * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1.
+ */
+static inline void prcmu_disable_stm_ape(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_clear(DB8500_PRCM_GPIOCR,
+                       DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
+       }
+}
+
+#else
+
+static inline void prcmu_enable_spi2(void) {}
+static inline void prcmu_disable_spi2(void) {}
+static inline void prcmu_enable_stm_mod_uart(void) {}
+static inline void prcmu_disable_stm_mod_uart(void) {}
+static inline void prcmu_enable_stm_ape(void) {}
+static inline void prcmu_disable_stm_ape(void) {}
+
 #endif
 
 /* PRCMU QoS APE OPP class */
 #define PRCMU_QOS_APE_OPP 1
 #define PRCMU_QOS_DDR_OPP 2
+#define PRCMU_QOS_ARM_OPP 3
 #define PRCMU_QOS_DEFAULT_VALUE -1
 
-#ifdef CONFIG_UX500_PRCMU_QOS_POWER
+#ifdef CONFIG_DBX500_PRCMU_QOS_POWER
 
 unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
 void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
index b86ee45c8b03fc1b57f233543bbd0f0859167532..10e038bac8dd106f742dc283aa69e7f5cbc495e7 100644 (file)
@@ -38,7 +38,8 @@ int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq);
 int mc13xxx_get_flags(struct mc13xxx *mc13xxx);
 
 int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx,
-               unsigned int mode, unsigned int channel, unsigned int *sample);
+               unsigned int mode, unsigned int channel,
+               u8 ato, bool atox, unsigned int *sample);
 
 #define MC13XXX_IRQ_ADCDONE    0
 #define MC13XXX_IRQ_ADCBISDONE 1
@@ -157,6 +158,18 @@ struct mc13xxx_buttons_platform_data {
        unsigned short b3on_key;
 };
 
+struct mc13xxx_ts_platform_data {
+       /* Delay between Touchscreen polarization and ADC Conversion.
+        * Given in clock ticks of a 32 kHz clock which gives a granularity of
+        * about 30.5ms */
+       u8 ato;
+
+#define MC13783_TS_ATO_FIRST false
+#define MC13783_TS_ATO_EACH  true
+       /* Use the ATO delay only for the first conversion or for each one */
+       bool atox;
+};
+
 struct mc13xxx_platform_data {
 #define MC13XXX_USE_TOUCHSCREEN (1 << 0)
 #define MC13XXX_USE_CODEC      (1 << 1)
@@ -167,6 +180,7 @@ struct mc13xxx_platform_data {
        struct mc13xxx_regulator_platform_data regulators;
        struct mc13xxx_leds_platform_data *leds;
        struct mc13xxx_buttons_platform_data *buttons;
+       struct mc13xxx_ts_platform_data touch;
 };
 
 #define MC13XXX_ADC_MODE_TS            1
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h
new file mode 100644 (file)
index 0000000..a2c6160
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Core driver interface to access RICOH_RC5T583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * Based on code
+ *      Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __LINUX_MFD_RC5T583_H
+#define __LINUX_MFD_RC5T583_H
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#define RC5T583_MAX_REGS               0xF8
+
+/* Maximum number of main interrupts */
+#define MAX_MAIN_INTERRUPT             5
+#define RC5T583_MAX_GPEDGE_REG         2
+#define RC5T583_MAX_INTERRUPT_MASK_REGS        9
+
+/* Interrupt enable register */
+#define RC5T583_INT_EN_SYS1    0x19
+#define RC5T583_INT_EN_SYS2    0x1D
+#define RC5T583_INT_EN_DCDC    0x41
+#define RC5T583_INT_EN_RTC     0xED
+#define RC5T583_INT_EN_ADC1    0x90
+#define RC5T583_INT_EN_ADC2    0x91
+#define RC5T583_INT_EN_ADC3    0x92
+
+/* Interrupt status registers (monitor regs in Ricoh)*/
+#define RC5T583_INTC_INTPOL    0xAD
+#define RC5T583_INTC_INTEN     0xAE
+#define RC5T583_INTC_INTMON    0xAF
+
+#define RC5T583_INT_MON_GRP    0xAF
+#define RC5T583_INT_MON_SYS1   0x1B
+#define RC5T583_INT_MON_SYS2   0x1F
+#define RC5T583_INT_MON_DCDC   0x43
+#define RC5T583_INT_MON_RTC    0xEE
+
+/* Interrupt clearing registers */
+#define RC5T583_INT_IR_SYS1    0x1A
+#define RC5T583_INT_IR_SYS2    0x1E
+#define RC5T583_INT_IR_DCDC    0x42
+#define RC5T583_INT_IR_RTC     0xEE
+#define RC5T583_INT_IR_ADCL    0x94
+#define RC5T583_INT_IR_ADCH    0x95
+#define RC5T583_INT_IR_ADCEND  0x96
+#define RC5T583_INT_IR_GPIOR   0xA9
+#define RC5T583_INT_IR_GPIOF   0xAA
+
+/* Sleep sequence registers */
+#define RC5T583_SLPSEQ1                0x21
+#define RC5T583_SLPSEQ2                0x22
+#define RC5T583_SLPSEQ3                0x23
+#define RC5T583_SLPSEQ4                0x24
+#define RC5T583_SLPSEQ5                0x25
+#define RC5T583_SLPSEQ6                0x26
+#define RC5T583_SLPSEQ7                0x27
+#define RC5T583_SLPSEQ8                0x28
+#define RC5T583_SLPSEQ9                0x29
+#define RC5T583_SLPSEQ10       0x2A
+#define RC5T583_SLPSEQ11       0x2B
+
+/* Regulator registers */
+#define RC5T583_REG_DC0CTL     0x30
+#define RC5T583_REG_DC0DAC     0x31
+#define RC5T583_REG_DC0LATCTL  0x32
+#define RC5T583_REG_SR0CTL     0x33
+
+#define RC5T583_REG_DC1CTL     0x34
+#define RC5T583_REG_DC1DAC     0x35
+#define RC5T583_REG_DC1LATCTL  0x36
+#define RC5T583_REG_SR1CTL     0x37
+
+#define RC5T583_REG_DC2CTL     0x38
+#define RC5T583_REG_DC2DAC     0x39
+#define RC5T583_REG_DC2LATCTL  0x3A
+#define RC5T583_REG_SR2CTL     0x3B
+
+#define RC5T583_REG_DC3CTL     0x3C
+#define RC5T583_REG_DC3DAC     0x3D
+#define RC5T583_REG_DC3LATCTL  0x3E
+#define RC5T583_REG_SR3CTL     0x3F
+
+
+#define RC5T583_REG_LDOEN1     0x50
+#define RC5T583_REG_LDOEN2     0x51
+#define RC5T583_REG_LDODIS1    0x52
+#define RC5T583_REG_LDODIS2    0x53
+
+#define RC5T583_REG_LDO0DAC    0x54
+#define RC5T583_REG_LDO1DAC    0x55
+#define RC5T583_REG_LDO2DAC    0x56
+#define RC5T583_REG_LDO3DAC    0x57
+#define RC5T583_REG_LDO4DAC    0x58
+#define RC5T583_REG_LDO5DAC    0x59
+#define RC5T583_REG_LDO6DAC    0x5A
+#define RC5T583_REG_LDO7DAC    0x5B
+#define RC5T583_REG_LDO8DAC    0x5C
+#define RC5T583_REG_LDO9DAC    0x5D
+
+#define RC5T583_REG_DC0DAC_DS  0x60
+#define RC5T583_REG_DC1DAC_DS  0x61
+#define RC5T583_REG_DC2DAC_DS  0x62
+#define RC5T583_REG_DC3DAC_DS  0x63
+
+#define RC5T583_REG_LDO0DAC_DS 0x64
+#define RC5T583_REG_LDO1DAC_DS 0x65
+#define RC5T583_REG_LDO2DAC_DS 0x66
+#define RC5T583_REG_LDO3DAC_DS 0x67
+#define RC5T583_REG_LDO4DAC_DS 0x68
+#define RC5T583_REG_LDO5DAC_DS 0x69
+#define RC5T583_REG_LDO6DAC_DS 0x6A
+#define RC5T583_REG_LDO7DAC_DS 0x6B
+#define RC5T583_REG_LDO8DAC_DS 0x6C
+#define RC5T583_REG_LDO9DAC_DS 0x6D
+
+/* GPIO register base address */
+#define RC5T583_GPIO_IOSEL     0xA0
+#define RC5T583_GPIO_PDEN      0xA1
+#define RC5T583_GPIO_IOOUT     0xA2
+#define RC5T583_GPIO_PGSEL     0xA3
+#define RC5T583_GPIO_GPINV     0xA4
+#define RC5T583_GPIO_GPDEB     0xA5
+#define RC5T583_GPIO_GPEDGE1   0xA6
+#define RC5T583_GPIO_GPEDGE2   0xA7
+#define RC5T583_GPIO_EN_INT    0xA8
+#define RC5T583_GPIO_MON_IOIN  0xAB
+#define RC5T583_GPIO_GPOFUNC   0xAC
+
+/* RICOH_RC5T583 IRQ definitions */
+enum {
+       RC5T583_IRQ_ONKEY,
+       RC5T583_IRQ_ACOK,
+       RC5T583_IRQ_LIDOPEN,
+       RC5T583_IRQ_PREOT,
+       RC5T583_IRQ_CLKSTP,
+       RC5T583_IRQ_ONKEY_OFF,
+       RC5T583_IRQ_WD,
+       RC5T583_IRQ_EN_PWRREQ1,
+       RC5T583_IRQ_EN_PWRREQ2,
+       RC5T583_IRQ_PRE_VINDET,
+
+       RC5T583_IRQ_DC0LIM,
+       RC5T583_IRQ_DC1LIM,
+       RC5T583_IRQ_DC2LIM,
+       RC5T583_IRQ_DC3LIM,
+
+       RC5T583_IRQ_CTC,
+       RC5T583_IRQ_YALE,
+       RC5T583_IRQ_DALE,
+       RC5T583_IRQ_WALE,
+
+       RC5T583_IRQ_AIN1L,
+       RC5T583_IRQ_AIN2L,
+       RC5T583_IRQ_AIN3L,
+       RC5T583_IRQ_VBATL,
+       RC5T583_IRQ_VIN3L,
+       RC5T583_IRQ_VIN8L,
+       RC5T583_IRQ_AIN1H,
+       RC5T583_IRQ_AIN2H,
+       RC5T583_IRQ_AIN3H,
+       RC5T583_IRQ_VBATH,
+       RC5T583_IRQ_VIN3H,
+       RC5T583_IRQ_VIN8H,
+       RC5T583_IRQ_ADCEND,
+
+       RC5T583_IRQ_GPIO0,
+       RC5T583_IRQ_GPIO1,
+       RC5T583_IRQ_GPIO2,
+       RC5T583_IRQ_GPIO3,
+       RC5T583_IRQ_GPIO4,
+       RC5T583_IRQ_GPIO5,
+       RC5T583_IRQ_GPIO6,
+       RC5T583_IRQ_GPIO7,
+
+       /* Should be last entry */
+       RC5T583_MAX_IRQS,
+};
+
+/* Ricoh583 gpio definitions */
+enum {
+       RC5T583_GPIO0,
+       RC5T583_GPIO1,
+       RC5T583_GPIO2,
+       RC5T583_GPIO3,
+       RC5T583_GPIO4,
+       RC5T583_GPIO5,
+       RC5T583_GPIO6,
+       RC5T583_GPIO7,
+
+       /* Should be last entry */
+       RC5T583_MAX_GPIO,
+};
+
+enum {
+       RC5T583_DS_NONE,
+       RC5T583_DS_DC0,
+       RC5T583_DS_DC1,
+       RC5T583_DS_DC2,
+       RC5T583_DS_DC3,
+       RC5T583_DS_LDO0,
+       RC5T583_DS_LDO1,
+       RC5T583_DS_LDO2,
+       RC5T583_DS_LDO3,
+       RC5T583_DS_LDO4,
+       RC5T583_DS_LDO5,
+       RC5T583_DS_LDO6,
+       RC5T583_DS_LDO7,
+       RC5T583_DS_LDO8,
+       RC5T583_DS_LDO9,
+       RC5T583_DS_PSO0,
+       RC5T583_DS_PSO1,
+       RC5T583_DS_PSO2,
+       RC5T583_DS_PSO3,
+       RC5T583_DS_PSO4,
+       RC5T583_DS_PSO5,
+       RC5T583_DS_PSO6,
+       RC5T583_DS_PSO7,
+
+       /* Should be last entry */
+       RC5T583_DS_MAX,
+};
+
+/*
+ * Ricoh pmic RC5T583 supports sleep through two external controls.
+ * The output of gpios and regulator can be enable/disable through
+ * this external signals.
+ */
+enum {
+       RC5T583_EXT_PWRREQ1_CONTROL = 0x1,
+       RC5T583_EXT_PWRREQ2_CONTROL = 0x2,
+};
+
+struct rc5t583 {
+       struct device   *dev;
+       struct regmap   *regmap;
+       int             chip_irq;
+       int             irq_base;
+       struct mutex    irq_lock;
+       unsigned long   group_irq_en[MAX_MAIN_INTERRUPT];
+
+       /* For main interrupt bits in INTC */
+       uint8_t         intc_inten_reg;
+
+       /* For group interrupt bits and address */
+       uint8_t         irq_en_reg[RC5T583_MAX_INTERRUPT_MASK_REGS];
+
+       /* For gpio edge */
+       uint8_t         gpedge_reg[RC5T583_MAX_GPEDGE_REG];
+};
+
+/*
+ * rc5t583_platform_data: Platform data for ricoh rc5t583 pmu.
+ * The board specific data is provided through this structure.
+ * @irq_base: Irq base number on which this device registers their interrupts.
+ * @enable_shutdown: Enable shutdown through the input pin "shutdown".
+ */
+
+struct rc5t583_platform_data {
+       int             irq_base;
+       bool            enable_shutdown;
+};
+
+int rc5t583_write(struct device *dev, u8 reg, uint8_t val);
+int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val);
+int rc5t583_set_bits(struct device *dev, unsigned int reg,
+               unsigned int bit_mask);
+int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+               unsigned int bit_mask);
+int rc5t583_update(struct device *dev, unsigned int reg,
+               unsigned int val, unsigned int mask);
+int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id,
+       int ext_pwr_req, int deepsleep_slot_nr);
+int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base);
+int rc5t583_irq_exit(struct rc5t583 *rc5t583);
+
+#endif
index 8c54de674b4b7577e2da771880054765703b2831..8516fd1eaabc7882127d269bf4db58366e93bb57 100644 (file)
@@ -28,6 +28,7 @@ enum stmpe_partnum {
        STMPE1601,
        STMPE2401,
        STMPE2403,
+       STMPE_NBR_PARTS
 };
 
 /*
index 0dc98044d8b78ce4eab56245d4160373d7cba6d3..f5171dbf8850c5c036e2e431ade03382bbe21983 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef MFD_TMIO_H
 #define MFD_TMIO_H
 
+#include <linux/device.h>
 #include <linux/fb.h>
 #include <linux/io.h>
+#include <linux/jiffies.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 
@@ -64,8 +66,8 @@
 #define TMIO_MMC_SDIO_IRQ              (1 << 2)
 /*
  * Some platforms can detect card insertion events with controller powered
- * down, in which case they have to call tmio_mmc_cd_wakeup() to power up the
- * controller and report the event to the driver.
+ * down, using a GPIO IRQ, in which case they have to fill in cd_irq, cd_gpio,
+ * and cd_flags fields of struct tmio_mmc_data.
  */
 #define TMIO_MMC_HAS_COLD_CD           (1 << 3)
 /*
  * idle before writing to some registers.
  */
 #define TMIO_MMC_HAS_IDLE_WAIT         (1 << 4)
+/*
+ * A GPIO is used for card hotplug detection. We need an extra flag for this,
+ * because 0 is a valid GPIO number too, and requiring users to specify
+ * cd_gpio < 0 to disable GPIO hotplug would break backwards compatibility.
+ */
+#define TMIO_MMC_USE_GPIO_CD           (1 << 5)
 
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
 int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
@@ -97,19 +105,23 @@ struct tmio_mmc_data {
        u32                             ocr_mask;       /* available voltages */
        struct tmio_mmc_dma             *dma;
        struct device                   *dev;
-       bool                            power;
+       unsigned int                    cd_gpio;
        void (*set_pwr)(struct platform_device *host, int state);
        void (*set_clk_div)(struct platform_device *host, int state);
        int (*get_cd)(struct platform_device *host);
        int (*write16_hook)(struct tmio_mmc_host *host, int addr);
 };
 
+/*
+ * This function is deprecated and will be removed soon. Please, convert your
+ * platform to use drivers/mmc/core/cd-gpio.c
+ */
+#include <linux/mmc/host.h>
 static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
 {
-       if (pdata && !pdata->power) {
-               pdata->power = true;
-               pm_runtime_get(pdata->dev);
-       }
+       if (pdata)
+               mmc_detect_change(dev_get_drvdata(pdata->dev),
+                                 msecs_to_jiffies(100));
 }
 
 /*
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
new file mode 100644 (file)
index 0000000..38e31c5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Core driver interface for TI TPS65090 PMIC family
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_MFD_TPS65090_H
+#define __LINUX_MFD_TPS65090_H
+
+struct tps65090_subdev_info {
+       int             id;
+       const char      *name;
+       void            *platform_data;
+};
+
+struct tps65090_platform_data {
+       int irq_base;
+       int num_subdevs;
+       struct tps65090_subdev_info *subdevs;
+};
+
+/*
+ * NOTE: the functions below are not intended for use outside
+ * of the TPS65090 sub-device drivers
+ */
+extern int tps65090_write(struct device *dev, int reg, uint8_t val);
+extern int tps65090_read(struct device *dev, int reg, uint8_t *val);
+extern int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num);
+extern int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num);
+
+#endif /*__LINUX_MFD_TPS65090_H */
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
new file mode 100644 (file)
index 0000000..e030ef9
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * linux/mfd/tps65217.h
+ *
+ * Functions to access TPS65217 power management chip.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_MFD_TPS65217_H
+#define __LINUX_MFD_TPS65217_H
+
+#include <linux/i2c.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/* I2C ID for TPS65217 part */
+#define TPS65217_I2C_ID                        0x24
+
+/* All register addresses */
+#define TPS65217_REG_CHIPID            0X00
+#define TPS65217_REG_PPATH             0X01
+#define TPS65217_REG_INT               0X02
+#define TPS65217_REG_CHGCONFIG0                0X03
+#define TPS65217_REG_CHGCONFIG1                0X04
+#define TPS65217_REG_CHGCONFIG2                0X05
+#define TPS65217_REG_CHGCONFIG3                0X06
+#define TPS65217_REG_WLEDCTRL1         0X07
+#define TPS65217_REG_WLEDCTRL2         0X08
+#define TPS65217_REG_MUXCTRL           0X09
+#define TPS65217_REG_STATUS            0X0A
+#define TPS65217_REG_PASSWORD          0X0B
+#define TPS65217_REG_PGOOD             0X0C
+#define TPS65217_REG_DEFPG             0X0D
+#define TPS65217_REG_DEFDCDC1          0X0E
+#define TPS65217_REG_DEFDCDC2          0X0F
+#define TPS65217_REG_DEFDCDC3          0X10
+#define TPS65217_REG_DEFSLEW           0X11
+#define TPS65217_REG_DEFLDO1           0X12
+#define TPS65217_REG_DEFLDO2           0X13
+#define TPS65217_REG_DEFLS1            0X14
+#define TPS65217_REG_DEFLS2            0X15
+#define TPS65217_REG_ENABLE            0X16
+#define TPS65217_REG_DEFUVLO           0X18
+#define TPS65217_REG_SEQ1              0X19
+#define TPS65217_REG_SEQ2              0X1A
+#define TPS65217_REG_SEQ3              0X1B
+#define TPS65217_REG_SEQ4              0X1C
+#define TPS65217_REG_SEQ5              0X1D
+#define TPS65217_REG_SEQ6              0X1E
+
+/* Register field definitions */
+#define TPS65217_CHIPID_CHIP_MASK      0xF0
+#define TPS65217_CHIPID_REV_MASK       0x0F
+
+#define TPS65217_PPATH_ACSINK_ENABLE   BIT(7)
+#define TPS65217_PPATH_USBSINK_ENABLE  BIT(6)
+#define TPS65217_PPATH_AC_PW_ENABLE    BIT(5)
+#define TPS65217_PPATH_USB_PW_ENABLE   BIT(4)
+#define TPS65217_PPATH_AC_CURRENT_MASK 0x0C
+#define TPS65217_PPATH_USB_CURRENT_MASK        0x03
+
+#define TPS65217_INT_PBM               BIT(6)
+#define TPS65217_INT_ACM               BIT(5)
+#define TPS65217_INT_USBM              BIT(4)
+#define TPS65217_INT_PBI               BIT(2)
+#define TPS65217_INT_ACI               BIT(1)
+#define TPS65217_INT_USBI              BIT(0)
+
+#define TPS65217_CHGCONFIG0_TREG       BIT(7)
+#define TPS65217_CHGCONFIG0_DPPM       BIT(6)
+#define TPS65217_CHGCONFIG0_TSUSP      BIT(5)
+#define TPS65217_CHGCONFIG0_TERMI      BIT(4)
+#define TPS65217_CHGCONFIG0_ACTIVE     BIT(3)
+#define TPS65217_CHGCONFIG0_CHGTOUT    BIT(2)
+#define TPS65217_CHGCONFIG0_PCHGTOUT   BIT(1)
+#define TPS65217_CHGCONFIG0_BATTEMP    BIT(0)
+
+#define TPS65217_CHGCONFIG1_TMR_MASK   0xC0
+#define TPS65217_CHGCONFIG1_TMR_ENABLE BIT(5)
+#define TPS65217_CHGCONFIG1_NTC_TYPE   BIT(4)
+#define TPS65217_CHGCONFIG1_RESET      BIT(3)
+#define TPS65217_CHGCONFIG1_TERM       BIT(2)
+#define TPS65217_CHGCONFIG1_SUSP       BIT(1)
+#define TPS65217_CHGCONFIG1_CHG_EN     BIT(0)
+
+#define TPS65217_CHGCONFIG2_DYNTMR     BIT(7)
+#define TPS65217_CHGCONFIG2_VPREGHG    BIT(6)
+#define TPS65217_CHGCONFIG2_VOREG_MASK 0x30
+
+#define TPS65217_CHGCONFIG3_ICHRG_MASK 0xC0
+#define TPS65217_CHGCONFIG3_DPPMTH_MASK        0x30
+#define TPS65217_CHGCONFIG2_PCHRGT     BIT(3)
+#define TPS65217_CHGCONFIG2_TERMIF     0x06
+#define TPS65217_CHGCONFIG2_TRANGE     BIT(0)
+
+#define TPS65217_WLEDCTRL1_ISINK_ENABLE        BIT(3)
+#define TPS65217_WLEDCTRL1_ISEL                BIT(2)
+#define TPS65217_WLEDCTRL1_FDIM_MASK   0x03
+
+#define TPS65217_WLEDCTRL2_DUTY_MASK   0x7F
+
+#define TPS65217_MUXCTRL_MUX_MASK      0x07
+
+#define TPS65217_STATUS_OFF            BIT(7)
+#define TPS65217_STATUS_ACPWR          BIT(3)
+#define TPS65217_STATUS_USBPWR         BIT(2)
+#define TPS65217_STATUS_PB             BIT(0)
+
+#define TPS65217_PASSWORD_REGS_UNLOCK  0x7D
+
+#define TPS65217_PGOOD_LDO3_PG         BIT(6)
+#define TPS65217_PGOOD_LDO4_PG         BIT(5)
+#define TPS65217_PGOOD_DC1_PG          BIT(4)
+#define TPS65217_PGOOD_DC2_PG          BIT(3)
+#define TPS65217_PGOOD_DC3_PG          BIT(2)
+#define TPS65217_PGOOD_LDO1_PG         BIT(1)
+#define TPS65217_PGOOD_LDO2_PG         BIT(0)
+
+#define TPS65217_DEFPG_LDO1PGM         BIT(3)
+#define TPS65217_DEFPG_LDO2PGM         BIT(2)
+#define TPS65217_DEFPG_PGDLY_MASK      0x03
+
+#define TPS65217_DEFDCDCX_XADJX                BIT(7)
+#define TPS65217_DEFDCDCX_DCDC_MASK    0x3F
+
+#define TPS65217_DEFSLEW_GO            BIT(7)
+#define TPS65217_DEFSLEW_GODSBL                BIT(6)
+#define TPS65217_DEFSLEW_PFM_EN1       BIT(5)
+#define TPS65217_DEFSLEW_PFM_EN2       BIT(4)
+#define TPS65217_DEFSLEW_PFM_EN3       BIT(3)
+#define TPS65217_DEFSLEW_SLEW_MASK     0x07
+
+#define TPS65217_DEFLDO1_LDO1_MASK     0x0F
+
+#define TPS65217_DEFLDO2_TRACK         BIT(6)
+#define TPS65217_DEFLDO2_LDO2_MASK     0x3F
+
+#define TPS65217_DEFLDO3_LDO3_EN       BIT(5)
+#define TPS65217_DEFLDO3_LDO3_MASK     0x1F
+
+#define TPS65217_DEFLDO4_LDO4_EN       BIT(5)
+#define TPS65217_DEFLDO4_LDO4_MASK     0x1F
+
+#define TPS65217_ENABLE_LS1_EN         BIT(6)
+#define TPS65217_ENABLE_LS2_EN         BIT(5)
+#define TPS65217_ENABLE_DC1_EN         BIT(4)
+#define TPS65217_ENABLE_DC2_EN         BIT(3)
+#define TPS65217_ENABLE_DC3_EN         BIT(2)
+#define TPS65217_ENABLE_LDO1_EN                BIT(1)
+#define TPS65217_ENABLE_LDO2_EN                BIT(0)
+
+#define TPS65217_DEFUVLO_UVLOHYS       BIT(2)
+#define TPS65217_DEFUVLO_UVLO_MASK     0x03
+
+#define TPS65217_SEQ1_DC1_SEQ_MASK     0xF0
+#define TPS65217_SEQ1_DC2_SEQ_MASK     0x0F
+
+#define TPS65217_SEQ2_DC3_SEQ_MASK     0xF0
+#define TPS65217_SEQ2_LDO1_SEQ_MASK    0x0F
+
+#define TPS65217_SEQ3_LDO2_SEQ_MASK    0xF0
+#define TPS65217_SEQ3_LDO3_SEQ_MASK    0x0F
+
+#define TPS65217_SEQ4_LDO4_SEQ_MASK    0xF0
+
+#define TPS65217_SEQ5_DLY1_MASK                0xC0
+#define TPS65217_SEQ5_DLY2_MASK                0x30
+#define TPS65217_SEQ5_DLY3_MASK                0x0C
+#define TPS65217_SEQ5_DLY4_MASK                0x03
+
+#define TPS65217_SEQ6_DLY5_MASK                0xC0
+#define TPS65217_SEQ6_DLY6_MASK                0x30
+#define TPS65217_SEQ6_SEQUP            BIT(2)
+#define TPS65217_SEQ6_SEQDWN           BIT(1)
+#define TPS65217_SEQ6_INSTDWN          BIT(0)
+
+#define TPS65217_MAX_REGISTER          0x1E
+#define TPS65217_PROTECT_NONE          0
+#define TPS65217_PROTECT_L1            1
+#define TPS65217_PROTECT_L2            2
+
+
+enum tps65217_regulator_id {
+       /* DCDC's */
+       TPS65217_DCDC_1,
+       TPS65217_DCDC_2,
+       TPS65217_DCDC_3,
+       /* LDOs */
+       TPS65217_LDO_1,
+       TPS65217_LDO_2,
+       TPS65217_LDO_3,
+       TPS65217_LDO_4,
+};
+
+#define TPS65217_MAX_REG_ID            TPS65217_LDO_4
+
+/* Number of step-down converters available */
+#define TPS65217_NUM_DCDC              3
+/* Number of LDO voltage regulators available */
+#define TPS65217_NUM_LDO               4
+/* Number of total regulators available */
+#define TPS65217_NUM_REGULATOR         (TPS65217_NUM_DCDC + TPS65217_NUM_LDO)
+
+/**
+ * struct tps65217_board - packages regulator init data
+ * @tps65217_regulator_data: regulator initialization values
+ *
+ * Board data may be used to initialize regulator.
+ */
+struct tps65217_board {
+       struct regulator_init_data *tps65217_init_data;
+};
+
+/**
+ * struct tps_info - packages regulator constraints
+ * @name:              Voltage regulator name
+ * @min_uV:            minimum micro volts
+ * @max_uV:            minimum micro volts
+ * @vsel_to_uv:                Function pointer to get voltage from selector
+ * @uv_to_vsel:                Function pointer to get selector from voltage
+ * @table:             Table for non-uniform voltage step-size
+ * @table_len:         Length of the voltage table
+ * @enable_mask:       Regulator enable mask bits
+ * @set_vout_reg:      Regulator output voltage set register
+ * @set_vout_mask:     Regulator output voltage set mask
+ *
+ * This data is used to check the regualtor voltage limits while setting.
+ */
+struct tps_info {
+       const char *name;
+       int min_uV;
+       int max_uV;
+       int (*vsel_to_uv)(unsigned int vsel);
+       int (*uv_to_vsel)(int uV, unsigned int *vsel);
+       const int *table;
+       unsigned int table_len;
+       unsigned int enable_mask;
+       unsigned int set_vout_reg;
+       unsigned int set_vout_mask;
+};
+
+/**
+ * struct tps65217 - tps65217 sub-driver chip access routines
+ *
+ * Device data may be used to access the TPS65217 chip
+ */
+
+struct tps65217 {
+       struct device *dev;
+       struct tps65217_board *pdata;
+       struct regulator_desc desc[TPS65217_NUM_REGULATOR];
+       struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
+       struct tps_info *info[TPS65217_NUM_REGULATOR];
+       struct regmap *regmap;
+
+       /* Client devices */
+       struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR];
+};
+
+static inline struct tps65217 *dev_to_tps65217(struct device *dev)
+{
+       return dev_get_drvdata(dev);
+}
+
+int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
+                                       unsigned int *val);
+int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
+                       unsigned int val, unsigned int level);
+int tps65217_set_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level);
+int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int level);
+
+#endif /*  __LINUX_MFD_TPS65217_H */
index 76700b5eee92d29cbb1c75d5780dadc3d9e95242..1c6c2860d1a60a6350ff46e7d45321ed8be95a80 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __LINUX_MFD_TPS65910_H
 #define __LINUX_MFD_TPS65910_H
 
+#include <linux/gpio.h>
+
 /* TPS chip id list */
 #define TPS65910                       0
 #define TPS65911                       1
 
 
 /*Register GPIO  (0x80) register.RegisterDescription */
+#define GPIO_SLEEP_MASK                         0x80
+#define GPIO_SLEEP_SHIFT                        7
 #define GPIO_DEB_MASK                           0x10
 #define GPIO_DEB_SHIFT                          4
 #define GPIO_PUEN_MASK                          0x08
 #define TPS65910_GPIO_STS                              BIT(1)
 #define TPS65910_GPIO_SET                              BIT(0)
 
+/* Max number of TPS65910/11 GPIOs */
+#define TPS65910_NUM_GPIO                              6
+#define TPS65911_NUM_GPIO                              9
+#define TPS6591X_MAX_NUM_GPIO                          9
+
 /* Regulator Index Definitions */
 #define TPS65910_REG_VRTC                              0
 #define TPS65910_REG_VIO                               1
@@ -785,6 +794,7 @@ struct tps65910_board {
        int irq_base;
        int vmbch_threshold;
        int vmbch2_threshold;
+       bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
        unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
        struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
 };
@@ -796,6 +806,7 @@ struct tps65910_board {
 struct tps65910 {
        struct device *dev;
        struct i2c_client *i2c_client;
+       struct regmap *regmap;
        struct mutex io_mutex;
        unsigned int id;
        int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest);
index dc3e050116898457e410b4cbc0c14f2cb6c81171..893267bb622932d9299f6f81f87c5d87ef0d0fe0 100644 (file)
@@ -22,7 +22,6 @@ struct wm8994_ldo_pdata {
        /** GPIOs to enable regulator, 0 or less if not available */
        int enable;
 
-       const char *supply;
        const struct regulator_init_data *init_data;
 };
 
index cf7982336103ffe86d78faedb61e1ce62529ac35..d8738a464b94a71822f191bdd45bcac29b01814c 100644 (file)
@@ -954,7 +954,7 @@ extern void truncate_pagecache(struct inode *inode, loff_t old, loff_t new);
 extern void truncate_setsize(struct inode *inode, loff_t newsize);
 extern int vmtruncate(struct inode *inode, loff_t offset);
 extern int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end);
-
+void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end);
 int truncate_inode_page(struct address_space *mapping, struct page *page);
 int generic_error_remove_page(struct address_space *mapping, struct page *page);
 
@@ -1258,6 +1258,8 @@ static inline void pgtable_page_dtor(struct page *page)
 extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, unsigned long * zones_size,
                unsigned long zone_start_pfn, unsigned long *zholes_size);
+extern void free_initmem(void);
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 /*
  * With CONFIG_HAVE_MEMBLOCK_NODE_MAP set, an architecture may initialise its
index 6faa145c81e3cd8c420deabca4a81b245a45e9ca..01beae78f07935e45d1a04ac544e8826ad90618a 100644 (file)
@@ -72,6 +72,8 @@ struct mmc_ext_csd {
        bool                    hpi_en;                 /* HPI enablebit */
        bool                    hpi;                    /* HPI support bit */
        unsigned int            hpi_cmd;                /* cmd used as HPI */
+       unsigned int            data_sector_size;       /* 512 bytes or 4KB */
+       unsigned int            data_tag_unit_size;     /* DATA TAG UNIT size */
        unsigned int            boot_ro_lock;           /* ro lock support */
        bool                    boot_ro_lockable;
        u8                      raw_partition_support;  /* 160 */
index a8e4697833187b563c7badfc6995fb356a77a329..cefaba038ccb6e3ec2ea83ad5596302debae7090 100644 (file)
@@ -12,8 +12,7 @@
 #define MMC_CD_GPIO_H
 
 struct mmc_host;
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
-                       unsigned int irq, unsigned long flags);
+int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio);
 void mmc_cd_gpio_free(struct mmc_host *host);
 
 #endif
index 2e6a681fceb26adeadcd6979bdeed6fabfd4d7af..1b431c728b9a057a150dff532fb3a47a4897e048 100644 (file)
@@ -175,7 +175,6 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
 
 extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
 extern void mmc_release_host(struct mmc_host *host);
-extern void mmc_do_release_host(struct mmc_host *host);
 extern int mmc_try_claim_host(struct mmc_host *host);
 
 extern int mmc_flush_cache(struct mmc_card *);
index aae5d1f1bb394af5a3d7bd1156bc11b67e556882..8f66e28f5a0f9a2b9f79c80a7c778eee7d4472ce 100644 (file)
@@ -76,7 +76,7 @@ struct mmc_data;
  * @num_slots: Number of slots available.
  * @verid: Denote Version ID.
  * @data_offset: Set the offset of DATA register according to VERID.
- * @pdev: Platform device associated with the MMC controller.
+ * @dev: Device associated with the MMC controller.
  * @pdata: Platform data associated with the MMC controller.
  * @slot: Slots sharing this MMC controller.
  * @fifo_depth: depth of FIFO.
@@ -87,6 +87,8 @@ struct mmc_data;
  * @push_data: Pointer to FIFO push function.
  * @pull_data: Pointer to FIFO pull function.
  * @quirks: Set of quirks that apply to specific versions of the IP.
+ * @irq_flags: The flags to be passed to request_irq.
+ * @irq: The irq value to be passed to request_irq.
  *
  * Locking
  * =======
@@ -153,7 +155,7 @@ struct dw_mci {
        u32                     fifoth_val;
        u16                     verid;
        u16                     data_offset;
-       struct platform_device  *pdev;
+       struct device           dev;
        struct dw_mci_board     *pdata;
        struct dw_mci_slot      *slot[MAX_MCI_SLOTS];
 
@@ -174,6 +176,8 @@ struct dw_mci {
        u32                     quirks;
 
        struct regulator        *vmmc;  /* Power regulator */
+       unsigned long           irq_flags; /* IRQ flags */
+       unsigned int            irq;
 };
 
 /* DMA ops for Internal/External DMAC interface */
index 91924e8c642b315423276bad5c547a3d75612f41..cbde4b7e675ed28eda507784c185d6ebc6b30215 100644 (file)
@@ -81,34 +81,11 @@ struct mmc_ios {
 
 struct mmc_host_ops {
        /*
-        * Hosts that support power saving can use the 'enable' and 'disable'
-        * methods to exit and enter power saving states. 'enable' is called
-        * when the host is claimed and 'disable' is called (or scheduled with
-        * a delay) when the host is released. The 'disable' is scheduled if
-        * the disable delay set by 'mmc_set_disable_delay()' is non-zero,
-        * otherwise 'disable' is called immediately. 'disable' may be
-        * scheduled repeatedly, to permit ever greater power saving at the
-        * expense of ever greater latency to re-enable. Rescheduling is
-        * determined by the return value of the 'disable' method. A positive
-        * value gives the delay in milliseconds.
-        *
-        * In the case where a host function (like set_ios) may be called
-        * with or without the host claimed, enabling and disabling can be
-        * done directly and will nest correctly. Call 'mmc_host_enable()' and
-        * 'mmc_host_lazy_disable()' for this purpose, but note that these
-        * functions must be paired.
-        *
-        * Alternatively, 'mmc_host_enable()' may be paired with
-        * 'mmc_host_disable()' which calls 'disable' immediately.  In this
-        * case the 'disable' method will be called with 'lazy' set to 0.
-        * This is mainly useful for error paths.
-        *
-        * Because lazy disable may be called from a work queue, the 'disable'
-        * method must claim the host when 'lazy' != 0, which will work
-        * correctly because recursion is detected and handled.
+        * 'enable' is called when the host is claimed and 'disable' is called
+        * when the host is released. 'enable' and 'disable' are deprecated.
         */
        int (*enable)(struct mmc_host *host);
-       int (*disable)(struct mmc_host *host, int lazy);
+       int (*disable)(struct mmc_host *host);
        /*
         * It is optional for the host to implement pre_req and post_req in
         * order to support double buffering of requests (prepare one
@@ -219,7 +196,7 @@ struct mmc_host {
 #define MMC_CAP_SPI            (1 << 4)        /* Talks only SPI protocols */
 #define MMC_CAP_NEEDS_POLL     (1 << 5)        /* Needs polling for card-detection */
 #define MMC_CAP_8_BIT_DATA     (1 << 6)        /* Can the host do 8 bit transfers */
-#define MMC_CAP_DISABLE                (1 << 7)        /* Can the host be disabled */
+
 #define MMC_CAP_NONREMOVABLE   (1 << 8)        /* Nonremovable e.g. eMMC */
 #define MMC_CAP_WAIT_WHILE_BUSY        (1 << 9)        /* Waits while card is busy */
 #define MMC_CAP_ERASE          (1 << 10)       /* Allow erase/trim commands */
@@ -259,6 +236,8 @@ struct mmc_host {
 #define MMC_CAP2_HS200         (MMC_CAP2_HS200_1_8V_SDR | \
                                 MMC_CAP2_HS200_1_2V_SDR)
 #define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
+#define MMC_CAP2_DETECT_ON_ERR (1 << 8)        /* On I/O err check card removal */
+#define MMC_CAP2_HC_ERASE_SZ   (1 << 9)        /* High-capacity erase size */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
        unsigned int        power_notify_type;
@@ -301,13 +280,7 @@ struct mmc_host {
        unsigned int            removed:1;      /* host is being removed */
 #endif
 
-       /* Only used with MMC_CAP_DISABLE */
-       int                     enabled;        /* host is enabled */
        int                     rescan_disable; /* disable card detection */
-       int                     nesting_cnt;    /* "enable" nesting count */
-       int                     en_dis_recurs;  /* detect recursion */
-       unsigned int            disable_delay;  /* disable delay in msecs */
-       struct delayed_work     disable;        /* disabling work */
 
        struct mmc_card         *card;          /* device attached to this host */
 
@@ -407,17 +380,8 @@ int mmc_card_awake(struct mmc_host *host);
 int mmc_card_sleep(struct mmc_host *host);
 int mmc_card_can_sleep(struct mmc_host *host);
 
-int mmc_host_enable(struct mmc_host *host);
-int mmc_host_disable(struct mmc_host *host);
-int mmc_host_lazy_disable(struct mmc_host *host);
 int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
 
-static inline void mmc_set_disable_delay(struct mmc_host *host,
-                                        unsigned int disable_delay)
-{
-       host->disable_delay = disable_delay;
-}
-
 /* Module parameter */
 extern bool mmc_assume_removable;
 
index fb9f6e116e1c7e0b79a2b25d55db8a48255e4bbf..b822a2cb6008d16d1dee1474c62d9a8301da754e 100644 (file)
@@ -274,6 +274,7 @@ struct _mmc_csd {
 #define EXT_CSD_FLUSH_CACHE            32      /* W */
 #define EXT_CSD_CACHE_CTRL             33      /* R/W */
 #define EXT_CSD_POWER_OFF_NOTIFICATION 34      /* R/W */
+#define EXT_CSD_DATA_SECTOR_SIZE       61      /* R */
 #define EXT_CSD_GP_SIZE_MULT           143     /* R/W */
 #define EXT_CSD_PARTITION_ATTRIBUTE    156     /* R/W */
 #define EXT_CSD_PARTITION_SUPPORT      160     /* RO */
@@ -315,6 +316,8 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME    247     /* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
 #define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
+#define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
+#define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
 #define EXT_CSD_HPI_FEATURES           503     /* RO */
 
 /*
index c750f85177d95cb7b849249ef9a0c007b7687992..e9051e1cb1ce38434d0443cfee5c7c74e43a1967 100644 (file)
@@ -90,6 +90,8 @@ struct sdhci_host {
 
        unsigned int quirks2;   /* More deviations from spec. */
 
+#define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
+
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
 
index 04ff452bf5c3e5eebd7251be8c8fd6c4d5861d0c..05f0e3db1c12b6681a820ff48519b0abe03b983b 100644 (file)
@@ -77,18 +77,15 @@ struct sh_mmcif_plat_data {
 
 /* CE_CLK_CTRL */
 #define CLK_ENABLE             (1 << 24) /* 1: output mmc clock */
-#define CLK_CLEAR              ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
-#define CLK_SUP_PCLK           ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
-#define CLKDIV_4               (1<<16) /* mmc clock frequency.
-                                        * n: bus clock/(2^(n+1)) */
-#define CLKDIV_256             (7<<16) /* mmc clock frequency. (see above) */
-#define SRSPTO_256             ((1 << 13) | (0 << 12)) /* resp timeout */
-#define SRBSYTO_29             ((1 << 11) | (1 << 10) |        \
-                                (1 << 9) | (1 << 8)) /* resp busy timeout */
-#define SRWDTO_29              ((1 << 7) | (1 << 6) |          \
-                                (1 << 5) | (1 << 4)) /* read/write timeout */
-#define SCCSTO_29              ((1 << 3) | (1 << 2) |          \
-                                (1 << 1) | (1 << 0)) /* ccs timeout */
+#define CLK_CLEAR              (0xf << 16)
+#define CLK_SUP_PCLK           (0xf << 16)
+#define CLKDIV_4               (1 << 16) /* mmc clock frequency.
+                                          * n: bus clock/(2^(n+1)) */
+#define CLKDIV_256             (7 << 16) /* mmc clock frequency. (see above) */
+#define SRSPTO_256             (2 << 12) /* resp timeout */
+#define SRBSYTO_29             (0xf << 8) /* resp busy timeout */
+#define SRWDTO_29              (0xf << 4) /* read/write timeout */
+#define SCCSTO_29              (0xf << 0) /* ccs timeout */
 
 /* CE_VERSION */
 #define SOFT_RST_ON            (1 << 31)
index 71b805451bd82d9175ae2dff99a467edb62a83b2..e94e620aeddc01a49b4f6073f54400ff343e66e2 100644 (file)
@@ -10,15 +10,29 @@ struct tmio_mmc_data;
 #define SH_MOBILE_SDHI_IRQ_SDCARD      "sdcard"
 #define SH_MOBILE_SDHI_IRQ_SDIO                "sdio"
 
+/**
+ * struct sh_mobile_sdhi_ops - SDHI driver callbacks
+ * @cd_wakeup:         trigger a card-detection run
+ */
+struct sh_mobile_sdhi_ops {
+       void (*cd_wakeup)(const struct platform_device *pdev);
+};
+
 struct sh_mobile_sdhi_info {
        int dma_slave_tx;
        int dma_slave_rx;
        unsigned long tmio_flags;
        unsigned long tmio_caps;
        u32 tmio_ocr_mask;      /* available MMC voltages */
+       unsigned int cd_gpio;
        struct tmio_mmc_data *pdata;
        void (*set_pwr)(struct platform_device *pdev, int state);
        int (*get_cd)(struct platform_device *pdev);
+
+       /* callbacks for board specific setup code */
+       int (*init)(struct platform_device *pdev,
+                   const struct sh_mobile_sdhi_ops *ops);
+       void (*cleanup)(struct platform_device *pdev);
 };
 
 #endif /* LINUX_MMC_SH_MOBILE_SDHI_H */
index 4598bf03e98b83756f4f8ecb5b4acdfafec379ad..fbcafe2ee13ec5da6b8f7a7db9dcfe38be6ec556 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/percpu.h>
 #include <asm/module.h>
 
-#include <trace/events/module.h>
-
 /* Not Yet Implemented */
 #define MODULE_SUPPORTED_DEVICE(name)
 
@@ -452,33 +450,11 @@ void symbol_put_addr(void *addr);
 
 /* Sometimes we know we already have a refcount, and it's easier not
    to handle the error case (which only happens with rmmod --wait). */
-static inline void __module_get(struct module *module)
-{
-       if (module) {
-               preempt_disable();
-               __this_cpu_inc(module->refptr->incs);
-               trace_module_get(module, _THIS_IP_);
-               preempt_enable();
-       }
-}
-
-static inline int try_module_get(struct module *module)
-{
-       int ret = 1;
-
-       if (module) {
-               preempt_disable();
+extern void __module_get(struct module *module);
 
-               if (likely(module_is_live(module))) {
-                       __this_cpu_inc(module->refptr->incs);
-                       trace_module_get(module, _THIS_IP_);
-               } else
-                       ret = 0;
-
-               preempt_enable();
-       }
-       return ret;
-}
+/* This is the Right Way to get a module: if it fails, it's being removed,
+ * so pretend it's not there. */
+extern bool try_module_get(struct module *module);
 
 extern void module_put(struct module *module);
 
index c47f4d60db0b0fb6cd05668212768efc439dc61d..ea36486378d85577ece5b6bceada24ef242d422e 100644 (file)
@@ -47,14 +47,11 @@ struct kernel_param_ops {
        void (*free)(void *arg);
 };
 
-/* Flag bits for kernel_param.flags */
-#define KPARAM_ISBOOL          2
-
 struct kernel_param {
        const char *name;
        const struct kernel_param_ops *ops;
        u16 perm;
-       u16 flags;
+       s16 level;
        union {
                void *arg;
                const struct kparam_string *str;
@@ -131,8 +128,40 @@ struct kparam_array
  * The ops can have NULL set or get functions.
  */
 #define module_param_cb(name, ops, arg, perm)                                \
-       __module_param_call(MODULE_PARAM_PREFIX,                              \
-                           name, ops, arg, __same_type((arg), bool *), perm)
+       __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0)
+
+/**
+ * <level>_param_cb - general callback for a module/cmdline parameter
+ *                    to be evaluated before certain initcall level
+ * @name: a valid C identifier which is the parameter name.
+ * @ops: the set & get operations for this parameter.
+ * @perm: visibility in sysfs.
+ *
+ * The ops can have NULL set or get functions.
+ */
+#define __level_param_cb(name, ops, arg, perm, level)                  \
+       __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level)
+
+#define core_param_cb(name, ops, arg, perm)            \
+       __level_param_cb(name, ops, arg, perm, 1)
+
+#define postcore_param_cb(name, ops, arg, perm)                \
+       __level_param_cb(name, ops, arg, perm, 2)
+
+#define arch_param_cb(name, ops, arg, perm)            \
+       __level_param_cb(name, ops, arg, perm, 3)
+
+#define subsys_param_cb(name, ops, arg, perm)          \
+       __level_param_cb(name, ops, arg, perm, 4)
+
+#define fs_param_cb(name, ops, arg, perm)              \
+       __level_param_cb(name, ops, arg, perm, 5)
+
+#define device_param_cb(name, ops, arg, perm)          \
+       __level_param_cb(name, ops, arg, perm, 6)
+
+#define late_param_cb(name, ops, arg, perm)            \
+       __level_param_cb(name, ops, arg, perm, 7)
 
 /* On alpha, ia64 and ppc64 relocations to global data cannot go into
    read-only sections (which is part of respective UNIX ABI on these
@@ -146,7 +175,7 @@ struct kparam_array
 
 /* This is the fundamental function for registering boot/module
    parameters. */
-#define __module_param_call(prefix, name, ops, arg, isbool, perm)      \
+#define __module_param_call(prefix, name, ops, arg, perm, level)       \
        /* Default value instead of permissions? */                     \
        static int __param_perm_check_##name __attribute__((unused)) =  \
        BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2))  \
@@ -155,8 +184,7 @@ struct kparam_array
        static struct kernel_param __moduleparam_const __param_##name   \
        __used                                                          \
     __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
-       = { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0,  \
-           { arg } }
+       = { __param_str_##name, ops, perm, level, { arg } }
 
 /* Obsolete - use module_param_cb() */
 #define module_param_call(name, set, get, arg, perm)                   \
@@ -164,8 +192,7 @@ struct kparam_array
                 { (void *)set, (void *)get };                          \
        __module_param_call(MODULE_PARAM_PREFIX,                        \
                            name, &__param_ops_##name, arg,             \
-                           __same_type(arg, bool *),                   \
-                           (perm) + sizeof(__check_old_set_param(set))*0)
+                           (perm) + sizeof(__check_old_set_param(set))*0, 0)
 
 /* We don't get oldget: it's often a new-style param_get_uint, etc. */
 static inline int
@@ -245,8 +272,7 @@ static inline void __kernel_param_unlock(void)
  */
 #define core_param(name, var, type, perm)                              \
        param_check_##type(name, &(var));                               \
-       __module_param_call("", name, &param_ops_##type,                \
-                           &var, __same_type(var, bool), perm)
+       __module_param_call("", name, &param_ops_##type, &var, perm, 0)
 #endif /* !MODULE */
 
 /**
@@ -264,7 +290,7 @@ static inline void __kernel_param_unlock(void)
                = { len, string };                                      \
        __module_param_call(MODULE_PARAM_PREFIX, name,                  \
                            &param_ops_string,                          \
-                           .str = &__param_string_##name, 0, perm);    \
+                           .str = &__param_string_##name, perm, 0);    \
        __MODULE_PARM_TYPE(name, "string")
 
 /**
@@ -292,6 +318,8 @@ extern int parse_args(const char *name,
                      char *args,
                      const struct kernel_param *params,
                      unsigned num,
+                     s16 level_min,
+                     s16 level_max,
                      int (*unknown)(char *param, char *val));
 
 /* Called by module remove. */
@@ -403,7 +431,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);
        __module_param_call(MODULE_PARAM_PREFIX, name,                  \
                            &param_array_ops,                           \
                            .arr = &__param_arr_##name,                 \
-                           __same_type(array[0], bool), perm);         \
+                           perm, 0);                                   \
        __MODULE_PARM_TYPE(name, "array of " #type)
 
 extern struct kernel_param_ops param_array_ops;
index 94e924e2ecd5799f29b8ac6ef4723411be1be9f5..3595a0236b0f9d8de9f7dbdae19d089b1b2adb9d 100644 (file)
@@ -29,8 +29,8 @@
 #include <linux/kernel.h>
 
 #include <asm/unaligned.h>
-#include <asm/system.h>
 #include <asm/io.h>
+#include <asm/barrier.h>
 
 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
 #define map_bankwidth(map) 1
index 834df8bf08b6e54951bc6483f0ffecbc47c7bd28..0987146b0637a1fd1f9a4ea03fb7040b1d4314cd 100644 (file)
@@ -438,7 +438,20 @@ enum limit_by4 {
 enum open_delegation_type4 {
        NFS4_OPEN_DELEGATE_NONE = 0,
        NFS4_OPEN_DELEGATE_READ = 1,
-       NFS4_OPEN_DELEGATE_WRITE = 2
+       NFS4_OPEN_DELEGATE_WRITE = 2,
+       NFS4_OPEN_DELEGATE_NONE_EXT = 3, /* 4.1 */
+};
+
+enum why_no_delegation4 { /* new to v4.1 */
+       WND4_NOT_WANTED = 0,
+       WND4_CONTENTION = 1,
+       WND4_RESOURCE = 2,
+       WND4_NOT_SUPP_FTYPE = 3,
+       WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4,
+       WND4_NOT_SUPP_UPGRADE = 5,
+       WND4_NOT_SUPP_DOWNGRADE = 6,
+       WND4_CANCELLED = 7,
+       WND4_IS_DIR = 8,
 };
 
 enum lock_type4 {
diff --git a/include/linux/nfsd/cld.h b/include/linux/nfsd/cld.h
new file mode 100644 (file)
index 0000000..f14a9ab
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Upcall description for nfsdcld communication
+ *
+ * Copyright (c) 2012 Red Hat, Inc.
+ * Author(s): Jeff Layton <jlayton@redhat.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _NFSD_CLD_H
+#define _NFSD_CLD_H
+
+/* latest upcall version available */
+#define CLD_UPCALL_VERSION 1
+
+/* defined by RFC3530 */
+#define NFS4_OPAQUE_LIMIT 1024
+
+enum cld_command {
+       Cld_Create,             /* create a record for this cm_id */
+       Cld_Remove,             /* remove record of this cm_id */
+       Cld_Check,              /* is this cm_id allowed? */
+       Cld_GraceDone,          /* grace period is complete */
+};
+
+/* representation of long-form NFSv4 client ID */
+struct cld_name {
+       uint16_t        cn_len;                         /* length of cm_id */
+       unsigned char   cn_id[NFS4_OPAQUE_LIMIT];       /* client-provided */
+} __attribute__((packed));
+
+/* message struct for communication with userspace */
+struct cld_msg {
+       uint8_t         cm_vers;                /* upcall version */
+       uint8_t         cm_cmd;                 /* upcall command */
+       int16_t         cm_status;              /* return code */
+       uint32_t        cm_xid;                 /* transaction id */
+       union {
+               int64_t         cm_gracetime;   /* grace period start time */
+               struct cld_name cm_name;
+       } __attribute__((packed)) cm_u;
+} __attribute__((packed));
+
+#endif /* !_NFSD_CLD_H */
index ba5d8494f2e1835277a794706b6a6519805a7ca3..fa7fb1d974589e001a637d0777cd4e856922d68b 100644 (file)
@@ -58,9 +58,6 @@ struct device_node {
        struct  kref kref;
        unsigned long _flags;
        void    *data;
-#if defined(CONFIG_EEH)
-       struct eeh_dev *edev;
-#endif
 #if defined(CONFIG_SPARC)
        char    *path_component_name;
        unsigned int unique_id;
@@ -75,13 +72,6 @@ struct of_phandle_args {
        uint32_t args[MAX_PHANDLE_ARGS];
 };
 
-#if defined(CONFIG_EEH)
-static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
-{
-       return dn->edev;
-}
-#endif
-
 #ifdef CONFIG_OF_DYNAMIC
 extern struct device_node *of_node_get(struct device_node *node);
 extern void of_node_put(struct device_node *node);
index b254052a49d7c283c281308de05850be47cbaffb..81733d12cbeaa822e965bc6d9fc7222b50c325cf 100644 (file)
@@ -50,7 +50,8 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
 extern int of_get_named_gpio_flags(struct device_node *np,
                const char *list_name, int index, enum of_gpio_flags *flags);
 
-extern unsigned int of_gpio_count(struct device_node *np);
+extern unsigned int of_gpio_named_count(struct device_node *np,
+                                       const char* propname);
 
 extern int of_mm_gpiochip_add(struct device_node *np,
                              struct of_mm_gpio_chip *mm_gc);
@@ -71,7 +72,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
        return -ENOSYS;
 }
 
-static inline unsigned int of_gpio_count(struct device_node *np)
+static inline unsigned int of_gpio_named_count(struct device_node *np,
+                                       const char* propname)
 {
        return 0;
 }
@@ -88,6 +90,27 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 
 #endif /* CONFIG_OF_GPIO */
 
+/**
+ * of_gpio_count - Count GPIOs for a device
+ * @np:                device node to count GPIOs for
+ *
+ * The function returns the count of GPIOs specified for a node.
+ *
+ * Note that the empty GPIO specifiers counts too. For example,
+ *
+ * gpios = <0
+ *          &pio1 1 2
+ *          0
+ *          &pio2 3 4>;
+ *
+ * defines four GPIOs (so this function will return 4), two of which
+ * are not specified.
+ */
+static inline unsigned int of_gpio_count(struct device_node *np)
+{
+       return of_gpio_named_count(np, "gpios");
+}
+
 /**
  * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API
  * @np:                device node to get GPIO from
index 38a423ed3c01d4468a57240a1ad3c5c33a418f9b..106c2ca9440be2f17a51d19cbd43969a5056454e 100644 (file)
@@ -100,7 +100,6 @@ typedef enum {
 #include <linux/wait.h>
 #include <linux/irqreturn.h>
 #include <linux/semaphore.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 
 /* Define this later. */
index f5bd679be46b50a93903b768754b7a363507c767..b067bd8c49d0ef9ed7e277ba0bb8564afafb48e6 100644 (file)
@@ -33,6 +33,7 @@ struct pid_namespace {
 #endif
        gid_t pid_gid;
        int hide_pid;
+       int reboot;     /* group exit code if this pidns was rebooted */
 };
 
 extern struct pid_namespace init_pid_ns;
@@ -48,6 +49,7 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
 extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
 extern void free_pid_ns(struct kref *kref);
 extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
+extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd);
 
 static inline void put_pid_ns(struct pid_namespace *ns)
 {
@@ -75,11 +77,15 @@ static inline void put_pid_ns(struct pid_namespace *ns)
 {
 }
 
-
 static inline void zap_pid_ns_processes(struct pid_namespace *ns)
 {
        BUG();
 }
+
+static inline int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
+{
+       return 0;
+}
 #endif /* CONFIG_PID_NS */
 
 extern struct pid_namespace *task_active_pid_ns(struct task_struct *tsk);
index e9a48234e69396650a7169ec0ba65e5f73e492ec..0d04cd69ab9b8c483895fbf7bab7cd691508e77a 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
  * Copyright (C) 2006 Nick Piggin
+ * Copyright (C) 2012 Konstantin Khlebnikov
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -257,4 +258,199 @@ static inline void radix_tree_preload_end(void)
        preempt_enable();
 }
 
+/**
+ * struct radix_tree_iter - radix tree iterator state
+ *
+ * @index:     index of current slot
+ * @next_index:        next-to-last index for this chunk
+ * @tags:      bit-mask for tag-iterating
+ *
+ * This radix tree iterator works in terms of "chunks" of slots.  A chunk is a
+ * subinterval of slots contained within one radix tree leaf node.  It is
+ * described by a pointer to its first slot and a struct radix_tree_iter
+ * which holds the chunk's position in the tree and its size.  For tagged
+ * iteration radix_tree_iter also holds the slots' bit-mask for one chosen
+ * radix tree tag.
+ */
+struct radix_tree_iter {
+       unsigned long   index;
+       unsigned long   next_index;
+       unsigned long   tags;
+};
+
+#define RADIX_TREE_ITER_TAG_MASK       0x00FF  /* tag index in lower byte */
+#define RADIX_TREE_ITER_TAGGED         0x0100  /* lookup tagged slots */
+#define RADIX_TREE_ITER_CONTIG         0x0200  /* stop at first hole */
+
+/**
+ * radix_tree_iter_init - initialize radix tree iterator
+ *
+ * @iter:      pointer to iterator state
+ * @start:     iteration starting index
+ * Returns:    NULL
+ */
+static __always_inline void **
+radix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start)
+{
+       /*
+        * Leave iter->tags uninitialized. radix_tree_next_chunk() will fill it
+        * in the case of a successful tagged chunk lookup.  If the lookup was
+        * unsuccessful or non-tagged then nobody cares about ->tags.
+        *
+        * Set index to zero to bypass next_index overflow protection.
+        * See the comment in radix_tree_next_chunk() for details.
+        */
+       iter->index = 0;
+       iter->next_index = start;
+       return NULL;
+}
+
+/**
+ * radix_tree_next_chunk - find next chunk of slots for iteration
+ *
+ * @root:      radix tree root
+ * @iter:      iterator state
+ * @flags:     RADIX_TREE_ITER_* flags and tag index
+ * Returns:    pointer to chunk first slot, or NULL if there no more left
+ *
+ * This function looks up the next chunk in the radix tree starting from
+ * @iter->next_index.  It returns a pointer to the chunk's first slot.
+ * Also it fills @iter with data about chunk: position in the tree (index),
+ * its end (next_index), and constructs a bit mask for tagged iterating (tags).
+ */
+void **radix_tree_next_chunk(struct radix_tree_root *root,
+                            struct radix_tree_iter *iter, unsigned flags);
+
+/**
+ * radix_tree_chunk_size - get current chunk size
+ *
+ * @iter:      pointer to radix tree iterator
+ * Returns:    current chunk size
+ */
+static __always_inline unsigned
+radix_tree_chunk_size(struct radix_tree_iter *iter)
+{
+       return iter->next_index - iter->index;
+}
+
+/**
+ * radix_tree_next_slot - find next slot in chunk
+ *
+ * @slot:      pointer to current slot
+ * @iter:      pointer to interator state
+ * @flags:     RADIX_TREE_ITER_*, should be constant
+ * Returns:    pointer to next slot, or NULL if there no more left
+ *
+ * This function updates @iter->index in the case of a successful lookup.
+ * For tagged lookup it also eats @iter->tags.
+ */
+static __always_inline void **
+radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
+{
+       if (flags & RADIX_TREE_ITER_TAGGED) {
+               iter->tags >>= 1;
+               if (likely(iter->tags & 1ul)) {
+                       iter->index++;
+                       return slot + 1;
+               }
+               if (!(flags & RADIX_TREE_ITER_CONTIG) && likely(iter->tags)) {
+                       unsigned offset = __ffs(iter->tags);
+
+                       iter->tags >>= offset;
+                       iter->index += offset + 1;
+                       return slot + offset + 1;
+               }
+       } else {
+               unsigned size = radix_tree_chunk_size(iter) - 1;
+
+               while (size--) {
+                       slot++;
+                       iter->index++;
+                       if (likely(*slot))
+                               return slot;
+                       if (flags & RADIX_TREE_ITER_CONTIG)
+                               break;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * radix_tree_for_each_chunk - iterate over chunks
+ *
+ * @slot:      the void** variable for pointer to chunk first slot
+ * @root:      the struct radix_tree_root pointer
+ * @iter:      the struct radix_tree_iter pointer
+ * @start:     iteration starting index
+ * @flags:     RADIX_TREE_ITER_* and tag index
+ *
+ * Locks can be released and reacquired between iterations.
+ */
+#define radix_tree_for_each_chunk(slot, root, iter, start, flags)      \
+       for (slot = radix_tree_iter_init(iter, start) ;                 \
+             (slot = radix_tree_next_chunk(root, iter, flags)) ;)
+
+/**
+ * radix_tree_for_each_chunk_slot - iterate over slots in one chunk
+ *
+ * @slot:      the void** variable, at the beginning points to chunk first slot
+ * @iter:      the struct radix_tree_iter pointer
+ * @flags:     RADIX_TREE_ITER_*, should be constant
+ *
+ * This macro is designed to be nested inside radix_tree_for_each_chunk().
+ * @slot points to the radix tree slot, @iter->index contains its index.
+ */
+#define radix_tree_for_each_chunk_slot(slot, iter, flags)              \
+       for (; slot ; slot = radix_tree_next_slot(slot, iter, flags))
+
+/**
+ * radix_tree_for_each_slot - iterate over non-empty slots
+ *
+ * @slot:      the void** variable for pointer to slot
+ * @root:      the struct radix_tree_root pointer
+ * @iter:      the struct radix_tree_iter pointer
+ * @start:     iteration starting index
+ *
+ * @slot points to radix tree slot, @iter->index contains its index.
+ */
+#define radix_tree_for_each_slot(slot, root, iter, start)              \
+       for (slot = radix_tree_iter_init(iter, start) ;                 \
+            slot || (slot = radix_tree_next_chunk(root, iter, 0)) ;    \
+            slot = radix_tree_next_slot(slot, iter, 0))
+
+/**
+ * radix_tree_for_each_contig - iterate over contiguous slots
+ *
+ * @slot:      the void** variable for pointer to slot
+ * @root:      the struct radix_tree_root pointer
+ * @iter:      the struct radix_tree_iter pointer
+ * @start:     iteration starting index
+ *
+ * @slot points to radix tree slot, @iter->index contains its index.
+ */
+#define radix_tree_for_each_contig(slot, root, iter, start)            \
+       for (slot = radix_tree_iter_init(iter, start) ;                 \
+            slot || (slot = radix_tree_next_chunk(root, iter,          \
+                               RADIX_TREE_ITER_CONTIG)) ;              \
+            slot = radix_tree_next_slot(slot, iter,                    \
+                               RADIX_TREE_ITER_CONTIG))
+
+/**
+ * radix_tree_for_each_tagged - iterate over tagged slots
+ *
+ * @slot:      the void** variable for pointer to slot
+ * @root:      the struct radix_tree_root pointer
+ * @iter:      the struct radix_tree_iter pointer
+ * @start:     iteration starting index
+ * @tag:       tag index
+ *
+ * @slot points to radix tree slot, @iter->index contains its index.
+ */
+#define radix_tree_for_each_tagged(slot, root, iter, start, tag)       \
+       for (slot = radix_tree_iter_init(iter, start) ;                 \
+            slot || (slot = radix_tree_next_chunk(root, iter,          \
+                             RADIX_TREE_ITER_TAGGED | tag)) ;          \
+            slot = radix_tree_next_slot(slot, iter,                    \
+                               RADIX_TREE_ITER_TAGGED))
+
 #endif /* _LINUX_RADIX_TREE_H */
index 76579f964a296d058b87e97f370f9758ff475559..7bd73bbdfd1bce8cbbb22a512ae221dd1eee700f 100644 (file)
@@ -26,7 +26,26 @@ enum ab8500_regulator_id {
        AB8500_NUM_REGULATORS,
 };
 
-/* AB8500 register initialization */
+/* AB9450 regulators */
+enum ab9540_regulator_id {
+       AB9540_LDO_AUX1,
+       AB9540_LDO_AUX2,
+       AB9540_LDO_AUX3,
+       AB9540_LDO_AUX4,
+       AB9540_LDO_INTCORE,
+       AB9540_LDO_TVOUT,
+       AB9540_LDO_USB,
+       AB9540_LDO_AUDIO,
+       AB9540_LDO_ANAMIC1,
+       AB9540_LDO_ANAMIC2,
+       AB9540_LDO_DMIC,
+       AB9540_LDO_ANA,
+       AB9540_SYSCLKREQ_2,
+       AB9540_SYSCLKREQ_4,
+       AB9540_NUM_REGULATORS,
+};
+
+/* AB8500 and AB9540 register initialization */
 struct ab8500_regulator_reg_init {
        int id;
        u8 value;
@@ -71,4 +90,53 @@ enum ab8500_regulator_reg {
        AB8500_NUM_REGULATOR_REGISTERS,
 };
 
+
+/* AB9540 registers */
+enum ab9540_regulator_reg {
+       AB9540_REGUREQUESTCTRL1,
+       AB9540_REGUREQUESTCTRL2,
+       AB9540_REGUREQUESTCTRL3,
+       AB9540_REGUREQUESTCTRL4,
+       AB9540_REGUSYSCLKREQ1HPVALID1,
+       AB9540_REGUSYSCLKREQ1HPVALID2,
+       AB9540_REGUHWHPREQ1VALID1,
+       AB9540_REGUHWHPREQ1VALID2,
+       AB9540_REGUHWHPREQ2VALID1,
+       AB9540_REGUHWHPREQ2VALID2,
+       AB9540_REGUSWHPREQVALID1,
+       AB9540_REGUSWHPREQVALID2,
+       AB9540_REGUSYSCLKREQVALID1,
+       AB9540_REGUSYSCLKREQVALID2,
+       AB9540_REGUVAUX4REQVALID,
+       AB9540_REGUMISC1,
+       AB9540_VAUDIOSUPPLY,
+       AB9540_REGUCTRL1VAMIC,
+       AB9540_VSMPS1REGU,
+       AB9540_VSMPS2REGU,
+       AB9540_VSMPS3REGU, /* NOTE! PRCMU register */
+       AB9540_VPLLVANAREGU,
+       AB9540_EXTSUPPLYREGU,
+       AB9540_VAUX12REGU,
+       AB9540_VRF1VAUX3REGU,
+       AB9540_VSMPS1SEL1,
+       AB9540_VSMPS1SEL2,
+       AB9540_VSMPS1SEL3,
+       AB9540_VSMPS2SEL1,
+       AB9540_VSMPS2SEL2,
+       AB9540_VSMPS2SEL3,
+       AB9540_VSMPS3SEL1, /* NOTE! PRCMU register */
+       AB9540_VSMPS3SEL2, /* NOTE! PRCMU register */
+       AB9540_VAUX1SEL,
+       AB9540_VAUX2SEL,
+       AB9540_VRF1VAUX3SEL,
+       AB9540_REGUCTRL2SPARE,
+       AB9540_VAUX4REQCTRL,
+       AB9540_VAUX4REGU,
+       AB9540_VAUX4SEL,
+       AB9540_REGUCTRLDISCH,
+       AB9540_REGUCTRLDISCH2,
+       AB9540_REGUCTRLDISCH3,
+       AB9540_NUM_REGULATOR_REGISTERS,
+};
+
 #endif
index 93f4d035076bc8f295fde5b0a6b5b89e4c5df9ff..fcabfb4873c8dd6e8466233de9d557be4bf2101e 100644 (file)
@@ -202,7 +202,8 @@ struct rtc_device
        struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */
        int pie_enabled;
        struct work_struct irqwork;
-
+       /* Some hardware can't support UIE mode */
+       int uie_unsupported;
 
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
        struct work_struct uie_task;
index 63d406554391a53302d87c85455f310648621b5c..54bd7cd7ecbd11449b9e15b49f9ab7e208e96413 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 
 struct rw_semaphore;
index 0c3854b0d4b180670563c461c8d0feaf4bd96c3a..81a173c0897d91c2d5b22b5370d282c7346bd8a9 100644 (file)
@@ -63,7 +63,6 @@ struct sched_param {
 #include <linux/nodemask.h>
 #include <linux/mm_types.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
index b160645f5599f51547694c1c1771d3e2b03bd04e..6aed0805927f8ea608e3bce754974d53a9bc372f 100644 (file)
@@ -3,6 +3,23 @@
 
 #include <linux/ioport.h>
 
+#ifdef CONFIG_SUPERH
+#define INTC_NR_IRQS   512
+#else
+#define INTC_NR_IRQS   1024
+#endif
+
+/*
+ * Convert back and forth between INTEVT and IRQ values.
+ */
+#ifdef CONFIG_CPU_HAS_INTEVT
+#define evt2irq(evt)           (((evt) >> 5) - 16)
+#define irq2evt(irq)           (((irq) + 16) << 5)
+#else
+#define evt2irq(evt)           (evt)
+#define irq2evt(irq)           (irq)
+#endif
+
 typedef unsigned char intc_enum;
 
 struct intc_vect {
index 192250bd49f508e5d1508a8fdef2527cf5f1fdd9..33370271b8b2c43ac65925619d15305d27a7018c 100644 (file)
@@ -501,7 +501,6 @@ struct sk_buff {
  */
 #include <linux/slab.h>
 
-#include <asm/system.h>
 
 /*
  * skb might have a dst pointer attached, refcounted or not.
index 573c809c33d9900b49ff0d1a29f31b499d377dab..a595dce6b0c7596d1481e2c87a2b55028c66a449 100644 (file)
@@ -190,7 +190,7 @@ size_t ksize(const void *);
 #endif
 
 /**
- * kcalloc - allocate memory for an array. The memory is set to zero.
+ * kmalloc_array - allocate memory for an array.
  * @n: number of elements.
  * @size: element size.
  * @flags: the type of memory to allocate.
@@ -240,11 +240,22 @@ size_t ksize(const void *);
  * for general use, and so are not documented here. For a full list of
  * potential flags, always refer to linux/gfp.h.
  */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
 {
        if (size != 0 && n > ULONG_MAX / size)
                return NULL;
-       return __kmalloc(n * size, flags | __GFP_ZERO);
+       return __kmalloc(n * size, flags);
+}
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+       return kmalloc_array(n, size, flags | __GFP_ZERO);
 }
 
 #if !defined(CONFIG_NUMA) && !defined(CONFIG_SLOB)
index ca122b36aec1220b2cf7762704306cb99c6ae635..c2f8c8bc56edd08183dd0dd22b4f7d3b39f1c63d 100644 (file)
@@ -22,7 +22,7 @@ enum stat_item {
        FREE_FROZEN,            /* Freeing to frozen slab */
        FREE_ADD_PARTIAL,       /* Freeing moves slab to partial list */
        FREE_REMOVE_PARTIAL,    /* Freeing removes last object */
-       ALLOC_FROM_PARTIAL,     /* Cpu slab acquired from partial list */
+       ALLOC_FROM_PARTIAL,     /* Cpu slab acquired from node partial list */
        ALLOC_SLAB,             /* Cpu slab acquired from page allocator */
        ALLOC_REFILL,           /* Refill cpu slab from slab freelist */
        ALLOC_NODE_MISMATCH,    /* Switching cpu slab */
@@ -38,7 +38,9 @@ enum stat_item {
        CMPXCHG_DOUBLE_CPU_FAIL,/* Failure of this_cpu_cmpxchg_double */
        CMPXCHG_DOUBLE_FAIL,    /* Number of times that cmpxchg double did not match */
        CPU_PARTIAL_ALLOC,      /* Used cpu partial on alloc */
-       CPU_PARTIAL_FREE,       /* USed cpu partial on free */
+       CPU_PARTIAL_FREE,       /* Refill cpu partial on free */
+       CPU_PARTIAL_NODE,       /* Refill cpu partial from node partial */
+       CPU_PARTIAL_DRAIN,      /* Drain cpu partial to node partial */
        NR_SLUB_STAT_ITEMS };
 
 struct kmem_cache_cpu {
index 8cc38d3bab0c57a79f68fe53e4915f9393335cba..10530d92c04b05bd56ab269974094ecfd2efbaab 100644 (file)
@@ -101,6 +101,22 @@ static inline void call_function_init(void) { }
  */
 int on_each_cpu(smp_call_func_t func, void *info, int wait);
 
+/*
+ * Call a function on processors specified by mask, which might include
+ * the local one.
+ */
+void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
+               void *info, bool wait);
+
+/*
+ * Call a function on each processor for which the supplied function
+ * cond_func returns a positive value. This may include the local
+ * processor.
+ */
+void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
+               smp_call_func_t func, void *info, bool wait,
+               gfp_t gfp_flags);
+
 /*
  * Mark the boot cpu "online" so that it can call console drivers in
  * printk() and can access its per-cpu storage.
@@ -132,6 +148,36 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
                local_irq_enable();             \
                0;                              \
        })
+/*
+ * Note we still need to test the mask even for UP
+ * because we actually can get an empty mask from
+ * code that on SMP might call us without the local
+ * CPU in the mask.
+ */
+#define on_each_cpu_mask(mask, func, info, wait) \
+       do {                                            \
+               if (cpumask_test_cpu(0, (mask))) {      \
+                       local_irq_disable();            \
+                       (func)(info);                   \
+                       local_irq_enable();             \
+               }                                       \
+       } while (0)
+/*
+ * Preemption is disabled here to make sure the cond_func is called under the
+ * same condtions in UP and SMP.
+ */
+#define on_each_cpu_cond(cond_func, func, info, wait, gfp_flags)\
+       do {                                                    \
+               void *__info = (info);                          \
+               preempt_disable();                              \
+               if ((cond_func)(0, __info)) {                   \
+                       local_irq_disable();                    \
+                       (func)(__info);                         \
+                       local_irq_enable();                     \
+               }                                               \
+               preempt_enable();                               \
+       } while (0)
+
 static inline void smp_send_reschedule(int cpu) { }
 #define num_booting_cpus()                     1
 #define smp_prepare_boot_cpu()                 do {} while (0)
index 363239087263a0fbb60d7bc1dc25c1ee59846817..7d537ced949aa83b33b4c20e32c991d2123ca5a5 100644 (file)
@@ -55,8 +55,8 @@
 #include <linux/kernel.h>
 #include <linux/stringify.h>
 #include <linux/bottom_half.h>
+#include <asm/barrier.h>
 
-#include <asm/system.h>
 
 /*
  * Must define these before including other files, inline functions need them
index e253ccd7a604c83e003a0db3475bd895b752765b..51df117abe46279223ed1f2a7cb911998aca5ecc 100644 (file)
@@ -67,7 +67,7 @@ _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags)
 #define _raw_spin_trylock_bh(lock) __raw_spin_trylock_bh(lock)
 #endif
 
-#ifdef CONFIG_INLINE_SPIN_UNLOCK
+#ifndef CONFIG_UNINLINE_SPIN_UNLOCK
 #define _raw_spin_unlock(lock) __raw_spin_unlock(lock)
 #endif
 
index c170edc3bf5f62d0c1cca31ae332c0a29c24389f..3b5e910d14ca47561ca8c2656b1f91cfb696ac45 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/cpumask.h>
 #include <linux/smp.h>
 #include <linux/list.h>
-#include <asm/system.h>
 
 /*
  * stop_cpu[s]() is simplistic per-cpu maximum priority cpu
index c14fe86dac594f069a08342f1790c03909586c41..0b8e3e6bdacf0b6af2e32541d6ad83cf52af8f6e 100644 (file)
@@ -190,7 +190,7 @@ extern int svc_rdma_xdr_encode_error(struct svcxprt_rdma *,
 extern void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *, int);
 extern void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *, int);
 extern void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *, int,
-                                           u32, u64, u32);
+                                           __be32, __be64, u32);
 extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *,
                                             struct rpcrdma_msg *,
                                             struct rpcrdma_msg *,
@@ -292,7 +292,7 @@ svc_rdma_get_reply_array(struct rpcrdma_msg *rmsgp)
        if (wr_ary) {
                rp_ary = (struct rpcrdma_write_array *)
                        &wr_ary->
-                       wc_array[wr_ary->wc_nchunks].wc_target.rs_length;
+                       wc_array[ntohl(wr_ary->wc_nchunks)].wc_target.rs_length;
 
                goto found_it;
        }
index b86b5c20617d93e361d462e20c0c3c87856214b6..8dc0ea7caf02baa404e8896d13351577a177547a 100644 (file)
@@ -21,6 +21,9 @@ struct bio;
 #define SWAP_FLAG_PRIO_SHIFT   0
 #define SWAP_FLAG_DISCARD      0x10000 /* discard swap cluster after use */
 
+#define SWAP_FLAGS_VALID       (SWAP_FLAG_PRIO_MASK | SWAP_FLAG_PREFER | \
+                                SWAP_FLAG_DISCARD)
+
 static inline int current_is_kswapd(void)
 {
        return current->flags & PF_KSWAPD;
diff --git a/include/linux/sysinfo.h b/include/linux/sysinfo.h
new file mode 100644 (file)
index 0000000..934335a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _LINUX_SYSINFO_H
+#define _LINUX_SYSINFO_H
+
+#include <linux/types.h>
+
+#define SI_LOAD_SHIFT  16
+struct sysinfo {
+       __kernel_long_t uptime;         /* Seconds since boot */
+       __kernel_ulong_t loads[3];      /* 1, 5, and 15 minute load averages */
+       __kernel_ulong_t totalram;      /* Total usable main memory size */
+       __kernel_ulong_t freeram;       /* Available memory size */
+       __kernel_ulong_t sharedram;     /* Amount of shared memory */
+       __kernel_ulong_t bufferram;     /* Memory used by buffers */
+       __kernel_ulong_t totalswap;     /* Total swap space size */
+       __kernel_ulong_t freeswap;      /* swap space still available */
+       __u16 procs;                    /* Number of current processes */
+       __u16 pad;                      /* Explicit padding for m68k */
+       __kernel_ulong_t totalhigh;     /* Total high memory size */
+       __kernel_ulong_t freehigh;      /* Available high memory size */
+       __u32 mem_unit;                 /* Memory unit size in bytes */
+       char _f[20-2*sizeof(__kernel_ulong_t)-sizeof(__u32)];   /* Padding: libc5 uses this.. */
+};
+
+#endif /* _LINUX_SYSINFO_H */
index b3061782dec3851765f3c398f67179744f4a39c2..33a92ead4d88163fce7b12d236c56dfd1772d379 100644 (file)
@@ -116,7 +116,6 @@ static inline struct timespec timespec_sub(struct timespec lhs,
 extern void read_persistent_clock(struct timespec *ts);
 extern void read_boot_clock(struct timespec *ts);
 extern int update_persistent_clock(struct timespec now);
-extern int no_sync_cmos_clock __read_mostly;
 void timekeeping_init(void);
 extern int timekeeping_suspended;
 
@@ -256,6 +255,7 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
        a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
        a->tv_nsec = ns;
 }
+
 #endif /* __KERNEL__ */
 
 #define NFDBITS                        __NFDBITS
index b75e1864ed19c9e151fb0b17f9ebc7bdf4a39b09..99bc88b1fc02734a30619038d2f9a7f430b4a951 100644 (file)
@@ -252,7 +252,7 @@ extern void ntp_clear(void);
 /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
 extern u64 ntp_tick_length(void);
 
-extern void second_overflow(void);
+extern int second_overflow(unsigned long secs);
 extern int do_adjtimex(struct timex *);
 extern void hardpps(const struct timespec *, const struct timespec *);
 
index a91ff403b3bfee4fc003975522429467a12e6d1e..9f47ab540f65e997b79b0a16c52332c564354234 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/tty_ldisc.h>
 #include <linux/mutex.h>
 
-#include <asm/system.h>
 
 
 /*
index 7d9a9e990ce6d0ae45aa73b87c883f60256310ff..1dee81c41ff14578c840dcfdf8f449983937267a 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <asm/current.h>
 
 typedef struct __wait_queue wait_queue_t;
index 43ba5b3ce2a3ac6be68b8aacd2b3740953113b25..ac40716b44e9a2a9ee1c13d1e878a195ce7215b0 100644 (file)
@@ -66,6 +66,7 @@ struct watchdog_device;
  * @ping:      The routine that sends a keepalive ping to the watchdog device.
  * @status:    The routine that shows the status of the watchdog device.
  * @set_timeout:The routine for setting the watchdog devices timeout value.
+ * @get_timeleft:The routine that get's the time that's left before a reset.
  * @ioctl:     The routines that handles extra ioctl calls.
  *
  * The watchdog_ops structure contains a list of low-level operations
@@ -82,6 +83,7 @@ struct watchdog_ops {
        int (*ping)(struct watchdog_device *);
        unsigned int (*status)(struct watchdog_device *);
        int (*set_timeout)(struct watchdog_device *, unsigned int);
+       unsigned int (*get_timeleft)(struct watchdog_device *);
        long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
 };
 
@@ -127,7 +129,7 @@ struct watchdog_device {
 #endif
 
 /* Use the following function to set the nowayout feature */
-static inline void watchdog_set_nowayout(struct watchdog_device *wdd, int nowayout)
+static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout)
 {
        if (nowayout)
                set_bit(WDOG_NO_WAY_OUT, &wdd->status);
index 03c85d7387fb7be265dad680dd50ba13b5425341..6a198e46ab6e1c50cdff7fe76d58b3a4afb43d43 100644 (file)
@@ -23,6 +23,7 @@ int xen_create_contiguous_region(unsigned long vstart, unsigned int order,
 
 void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
 
+struct vm_area_struct;
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
                               unsigned long addr,
                               unsigned long mfn, int nr,
index c24805c824b981d92b134e84792b66b515b0ef46..9d454f09f3b1522c850b99d31f517641e47a8503 100644 (file)
@@ -87,7 +87,6 @@ extern void mca_init(void);
 extern void sbus_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
-extern void free_initmem(void);
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
 #endif
@@ -400,7 +399,7 @@ static int __init do_early_param(char *param, char *val)
 
 void __init parse_early_options(char *cmdline)
 {
-       parse_args("early options", cmdline, NULL, 0, do_early_param);
+       parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param);
 }
 
 /* Arch code calls this early on, or if not, just before other parsing. */
@@ -503,7 +502,7 @@ asmlinkage void __init start_kernel(void)
        parse_early_param();
        parse_args("Booting kernel", static_command_line, __start___param,
                   __stop___param - __start___param,
-                  &unknown_bootoption);
+                  0, 0, &unknown_bootoption);
 
        jump_label_init();
 
@@ -699,16 +698,69 @@ int __init_or_module do_one_initcall(initcall_t fn)
 }
 
 
-extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
+extern initcall_t __initcall_start[];
+extern initcall_t __initcall0_start[];
+extern initcall_t __initcall1_start[];
+extern initcall_t __initcall2_start[];
+extern initcall_t __initcall3_start[];
+extern initcall_t __initcall4_start[];
+extern initcall_t __initcall5_start[];
+extern initcall_t __initcall6_start[];
+extern initcall_t __initcall7_start[];
+extern initcall_t __initcall_end[];
+
+static initcall_t *initcall_levels[] __initdata = {
+       __initcall0_start,
+       __initcall1_start,
+       __initcall2_start,
+       __initcall3_start,
+       __initcall4_start,
+       __initcall5_start,
+       __initcall6_start,
+       __initcall7_start,
+       __initcall_end,
+};
+
+static char *initcall_level_names[] __initdata = {
+       "early parameters",
+       "core parameters",
+       "postcore parameters",
+       "arch parameters",
+       "subsys parameters",
+       "fs parameters",
+       "device parameters",
+       "late parameters",
+};
+
+static int __init ignore_unknown_bootoption(char *param, char *val)
+{
+       return 0;
+}
 
-static void __init do_initcalls(void)
+static void __init do_initcall_level(int level)
 {
+       extern const struct kernel_param __start___param[], __stop___param[];
        initcall_t *fn;
 
-       for (fn = __early_initcall_end; fn < __initcall_end; fn++)
+       strcpy(static_command_line, saved_command_line);
+       parse_args(initcall_level_names[level],
+                  static_command_line, __start___param,
+                  __stop___param - __start___param,
+                  level, level,
+                  ignore_unknown_bootoption);
+
+       for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
                do_one_initcall(*fn);
 }
 
+static void __init do_initcalls(void)
+{
+       int level;
+
+       for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
+               do_initcall_level(level);
+}
+
 /*
  * Ok, the machine is now initialized. None of the devices
  * have been touched yet, but the CPU subsystem is up and
@@ -732,7 +784,7 @@ static void __init do_pre_smp_initcalls(void)
 {
        initcall_t *fn;
 
-       for (fn = __initcall_start; fn < __early_initcall_end; fn++)
+       for (fn = __initcall_start; fn < __initcall0_start; fn++)
                do_one_initcall(*fn);
 }
 
index 845a28738d3a824e5c7a4cd583c28c9d793467cf..a6df704f521e01f628def526e97b38cca92bb3ed 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/syscalls.h>
+#include <linux/ptrace.h>
 
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
@@ -117,6 +118,7 @@ extern int sem_ctls[];
 
 static inline int compat_ipc_parse_version(int *cmd)
 {
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
        int version = *cmd & IPC_64;
 
        /* this is tricky: architectures that have support for the old
@@ -128,6 +130,10 @@ static inline int compat_ipc_parse_version(int *cmd)
        *cmd &= ~IPC_64;
 #endif
        return version;
+#else
+       /* With the asm-generic APIs, we always use the 64-bit versions. */
+       return IPC_64;
+#endif
 }
 
 static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
@@ -232,10 +238,9 @@ static inline int put_compat_semid_ds(struct semid64_ds *s,
        return err;
 }
 
-long compat_sys_semctl(int first, int second, int third, void __user *uptr)
+static long do_compat_semctl(int first, int second, int third, u32 pad)
 {
        union semun fourth;
-       u32 pad;
        int err, err2;
        struct semid64_ds s64;
        struct semid64_ds __user *up64;
@@ -243,10 +248,6 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 
        memset(&s64, 0, sizeof(s64));
 
-       if (!uptr)
-               return -EINVAL;
-       if (get_user(pad, (u32 __user *) uptr))
-               return -EFAULT;
        if ((third & (~IPC_64)) == SETVAL)
                fourth.val = (int) pad;
        else
@@ -305,6 +306,18 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
        return err;
 }
 
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
+long compat_sys_semctl(int first, int second, int third, void __user *uptr)
+{
+       u32 pad;
+
+       if (!uptr)
+               return -EINVAL;
+       if (get_user(pad, (u32 __user *) uptr))
+               return -EFAULT;
+       return do_compat_semctl(first, second, third, pad);
+}
+
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 {
        struct compat_msgbuf __user *up = uptr;
@@ -353,6 +366,37 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 out:
        return err;
 }
+#else
+long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
+{
+       return do_compat_semctl(semid, semnum, cmd, arg);
+}
+
+long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
+                      size_t msgsz, int msgflg)
+{
+       compat_long_t mtype;
+
+       if (get_user(mtype, &msgp->mtype))
+               return -EFAULT;
+       return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
+}
+
+long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
+                      size_t msgsz, long msgtyp, int msgflg)
+{
+       long err, mtype;
+
+       err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
+       if (err < 0)
+               goto out;
+
+       if (put_user(mtype, &msgp->mtype))
+               err = -EFAULT;
+ out:
+       return err;
+}
+#endif
 
 static inline int get_compat_msqid64(struct msqid64_ds *m64,
                                     struct compat_msqid64_ds __user *up64)
@@ -470,6 +514,7 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
        return err;
 }
 
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
                        void __user *uptr)
 {
@@ -485,6 +530,19 @@ long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
        uaddr = compat_ptr(third);
        return put_user(raddr, uaddr);
 }
+#else
+long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg)
+{
+       unsigned long ret;
+       long err;
+
+       err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret);
+       if (err)
+               return err;
+       force_successful_syscall_return();
+       return (long)ret;
+}
+#endif
 
 static inline int get_compat_shmid64_ds(struct shmid64_ds *s64,
                                        struct compat_shmid64_ds __user *up64)
index 5068e2a4e75f05f3c1b823b79ae67c94ffc09130..2251882daf53211745a35321589386e265640c07 100644 (file)
@@ -124,8 +124,8 @@ config INLINE_SPIN_LOCK_IRQSAVE
        def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \
                 ARCH_INLINE_SPIN_LOCK_IRQSAVE
 
-config INLINE_SPIN_UNLOCK
-       def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_SPIN_UNLOCK)
+config UNINLINE_SPIN_UNLOCK
+       bool
 
 config INLINE_SPIN_UNLOCK_BH
        def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_UNLOCK_BH
index 24e7cb0ba26a9b534eab5ef5b0ed39226f4cd802..3f9c97419f02a69dd180f08b963976649ac2de05 100644 (file)
@@ -36,6 +36,7 @@ config PREEMPT_VOLUNTARY
 config PREEMPT
        bool "Preemptible Kernel (Low-Latency Desktop)"
        select PREEMPT_COUNT
+       select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK
        help
          This option reduces the latency of the kernel by making
          all kernel code (that is not executing in a critical section)
index f346cedfe24d1ce2a0a4c803e9adeca62534c017..74ff8498809a0af4b60c9df461825f80c5007260 100644 (file)
 #include <asm/uaccess.h>
 
 /*
- * Note that the native side is already converted to a timespec, because
- * that's what we want anyway.
+ * Get/set struct timeval with struct timespec on the native side
  */
-static int compat_get_timeval(struct timespec *o,
-               struct compat_timeval __user *i)
+static int compat_get_timeval_convert(struct timespec *o,
+                                     struct compat_timeval __user *i)
 {
        long usec;
 
@@ -46,8 +45,8 @@ static int compat_get_timeval(struct timespec *o,
        return 0;
 }
 
-static int compat_put_timeval(struct compat_timeval __user *o,
-               struct timeval *i)
+static int compat_put_timeval_convert(struct compat_timeval __user *o,
+                                     struct timeval *i)
 {
        return (put_user(i->tv_sec, &o->tv_sec) ||
                put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
@@ -117,7 +116,7 @@ asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
        if (tv) {
                struct timeval ktv;
                do_gettimeofday(&ktv);
-               if (compat_put_timeval(tv, &ktv))
+               if (compat_put_timeval_convert(tv, &ktv))
                        return -EFAULT;
        }
        if (tz) {
@@ -135,7 +134,7 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
        struct timezone ktz;
 
        if (tv) {
-               if (compat_get_timeval(&kts, tv))
+               if (compat_get_timeval_convert(&kts, tv))
                        return -EFAULT;
        }
        if (tz) {
@@ -146,12 +145,29 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
        return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
+int get_compat_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
+{
+       return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
+                       __get_user(tv->tv_sec, &ctv->tv_sec) ||
+                       __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
+}
+EXPORT_SYMBOL_GPL(get_compat_timeval);
+
+int put_compat_timeval(const struct timeval *tv, struct compat_timeval __user *ctv)
+{
+       return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) ||
+                       __put_user(tv->tv_sec, &ctv->tv_sec) ||
+                       __put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
+}
+EXPORT_SYMBOL_GPL(put_compat_timeval);
+
 int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
 {
        return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
                        __get_user(ts->tv_sec, &cts->tv_sec) ||
                        __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
+EXPORT_SYMBOL_GPL(get_compat_timespec);
 
 int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
 {
@@ -161,6 +177,42 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
 }
 EXPORT_SYMBOL_GPL(put_compat_timespec);
 
+int compat_get_timeval(struct timeval *tv, const void __user *utv)
+{
+       if (COMPAT_USE_64BIT_TIME)
+               return copy_from_user(tv, utv, sizeof *tv) ? -EFAULT : 0;
+       else
+               return get_compat_timeval(tv, utv);
+}
+EXPORT_SYMBOL_GPL(compat_get_timeval);
+
+int compat_put_timeval(const struct timeval *tv, void __user *utv)
+{
+       if (COMPAT_USE_64BIT_TIME)
+               return copy_to_user(utv, tv, sizeof *tv) ? -EFAULT : 0;
+       else
+               return put_compat_timeval(tv, utv);
+}
+EXPORT_SYMBOL_GPL(compat_put_timeval);
+
+int compat_get_timespec(struct timespec *ts, const void __user *uts)
+{
+       if (COMPAT_USE_64BIT_TIME)
+               return copy_from_user(ts, uts, sizeof *ts) ? -EFAULT : 0;
+       else
+               return get_compat_timespec(ts, uts);
+}
+EXPORT_SYMBOL_GPL(compat_get_timespec);
+
+int compat_put_timespec(const struct timespec *ts, void __user *uts)
+{
+       if (COMPAT_USE_64BIT_TIME)
+               return copy_to_user(uts, ts, sizeof *ts) ? -EFAULT : 0;
+       else
+               return put_compat_timespec(ts, uts);
+}
+EXPORT_SYMBOL_GPL(compat_put_timespec);
+
 static long compat_nanosleep_restart(struct restart_block *restart)
 {
        struct compat_timespec __user *rmtp;
index 1010cc61931ff00f4f7f8890b07f0af66ef2ed1e..b96ad75b7e64c6474b02d4d91534659bc43eb252 100644 (file)
@@ -2162,10 +2162,9 @@ void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
        mutex_unlock(&callback_mutex);
 }
 
-int cpuset_cpus_allowed_fallback(struct task_struct *tsk)
+void cpuset_cpus_allowed_fallback(struct task_struct *tsk)
 {
        const struct cpuset *cs;
-       int cpu;
 
        rcu_read_lock();
        cs = task_cs(tsk);
@@ -2186,22 +2185,10 @@ int cpuset_cpus_allowed_fallback(struct task_struct *tsk)
         * changes in tsk_cs()->cpus_allowed. Otherwise we can temporary
         * set any mask even if it is not right from task_cs() pov,
         * the pending set_cpus_allowed_ptr() will fix things.
+        *
+        * select_fallback_rq() will fix things ups and set cpu_possible_mask
+        * if required.
         */
-
-       cpu = cpumask_any_and(&tsk->cpus_allowed, cpu_active_mask);
-       if (cpu >= nr_cpu_ids) {
-               /*
-                * Either tsk->cpus_allowed is wrong (see above) or it
-                * is actually empty. The latter case is only possible
-                * if we are racing with remove_tasks_in_empty_cpuset().
-                * Like above we can temporary set any mask and rely on
-                * set_cpus_allowed_ptr() as synchronization point.
-                */
-               do_set_cpus_allowed(tsk, cpu_possible_mask);
-               cpu = cpumask_any(cpu_active_mask);
-       }
-
-       return cpu;
 }
 
 void cpuset_init_current_mems_allowed(void)
index 3f88a45e6f0abdf08e8fff7dfae0dbd3210f6eec..1dc53bae56e1f6974a7f7cdb7f9d82815d85a22c 100644 (file)
@@ -53,7 +53,6 @@
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 #include "debug_core.h"
 
index 7179eac7b41cbf6e8d43f423d8a9ac0e8018efc9..07c9bbb94a0b3016e9b0d0d11d5c4f6a94cd1658 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/sched.h>
 #include <linux/kdb.h>
 #include <linux/nmi.h>
-#include <asm/system.h>
 #include "kdb_private.h"
 
 
index 68a2306522c8d972121676a94b96ddad1b25a243..6c6262f86c17785b53928fa1787467040c8d3938 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 
 
index 3db1909faed9331488cecad09e10359db175a746..d8bd3b425fa78413f94c9278f481672faebb999c 100644 (file)
@@ -474,7 +474,7 @@ static void close_files(struct files_struct * files)
                i = j * __NFDBITS;
                if (i >= fdt->max_fds)
                        break;
-               set = fdt->open_fds->fds_bits[j++];
+               set = fdt->open_fds[j++];
                while (set) {
                        if (set & 1) {
                                struct file * file = xchg(&fdt->fd[i], NULL);
index 5a38bf4de641d249ddc590d4397e6b96e8fbfbef..cf1a4a68ce444f03218ea0adbbd1f0ea178cc4d0 100644 (file)
@@ -13,7 +13,7 @@ config GENERIC_HARDIRQS
 # Options selectable by the architecture code
 
 # Make sparse irq Kconfig switch below available
-config HAVE_SPARSE_IRQ
+config MAY_HAVE_SPARSE_IRQ
        bool
 
 # Enable the generic irq autoprobe mechanism
@@ -56,13 +56,22 @@ config GENERIC_IRQ_CHIP
 config IRQ_DOMAIN
        bool
 
+config IRQ_DOMAIN_DEBUG
+       bool "Expose hardware/virtual IRQ mapping via debugfs"
+       depends on IRQ_DOMAIN && DEBUG_FS
+       help
+         This option will show the mapping relationship between hardware irq
+         numbers and Linux irq numbers. The mapping is exposed via debugfs
+         in the file "virq_mapping".
+
+         If you don't know what this means you don't need it.
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
 
 config SPARSE_IRQ
-       bool "Support sparse irq numbering"
-       depends on HAVE_SPARSE_IRQ
+       bool "Support sparse irq numbering" if MAY_HAVE_SPARSE_IRQ
        ---help---
 
          Sparse irq numbering is useful for distro kernels that want
index af48e59bc2ff4ebd46b08bc9898e328540039cc2..3601f3fbf67c8808cb0223206713b1d1aeeb31bb 100644 (file)
@@ -632,7 +632,7 @@ unsigned int irq_linear_revmap(struct irq_domain *domain,
        return revmap[hwirq];
 }
 
-#ifdef CONFIG_VIRQ_DEBUG
+#ifdef CONFIG_IRQ_DOMAIN_DEBUG
 static int virq_debug_show(struct seq_file *m, void *private)
 {
        unsigned long flags;
@@ -668,7 +668,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
                        data = irq_desc_get_chip_data(desc);
                        seq_printf(m, "0x%16p  ", data);
 
-                       if (desc->irq_data.domain->of_node)
+                       if (desc->irq_data.domain && desc->irq_data.domain->of_node)
                                p = desc->irq_data.domain->of_node->full_name;
                        else
                                p = none;
@@ -695,14 +695,14 @@ static const struct file_operations virq_debug_fops = {
 
 static int __init irq_debugfs_init(void)
 {
-       if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root,
+       if (debugfs_create_file("irq_domain_mapping", S_IRUGO, NULL,
                                 NULL, &virq_debug_fops) == NULL)
                return -ENOMEM;
 
        return 0;
 }
 __initcall(irq_debugfs_init);
-#endif /* CONFIG_VIRQ_DEBUG */
+#endif /* CONFIG_IRQ_DOMAIN_DEBUG */
 
 int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
                          irq_hw_number_t hwirq)
index a6a675cb9818ad43728ba7246472f62b44fcd23b..4e2e472f6aeb35e5fb78e9a6ccdcc4c08fae57e3 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/page.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 
 /* Per cpu memory for storing cpu states in case of system crash. */
@@ -1359,6 +1358,10 @@ static int __init parse_crashkernel_simple(char          *cmdline,
 
        if (*cur == '@')
                *crash_base = memparse(cur+1, &cur);
+       else if (*cur != ' ' && *cur != '\0') {
+               pr_warning("crashkernel: unrecognized char\n");
+               return -EINVAL;
+       }
 
        return 0;
 }
@@ -1462,7 +1465,9 @@ static int __init crash_save_vmcoreinfo_init(void)
 
        VMCOREINFO_SYMBOL(init_uts_ns);
        VMCOREINFO_SYMBOL(node_online_map);
+#ifdef CONFIG_MMU
        VMCOREINFO_SYMBOL(swapper_pg_dir);
+#endif
        VMCOREINFO_SYMBOL(_stext);
        VMCOREINFO_SYMBOL(vmlist);
 
index 2c932760fd33d152016e62431cba5c986f65957f..78ac6ec1e425f8dc03fe27eccd9beee2a233d90a 100644 (file)
@@ -105,6 +105,7 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
 
 /* Block module loading/unloading? */
 int modules_disabled = 0;
+core_param(nomodule, modules_disabled, bint, 0);
 
 /* Waiting for a module to finish initializing? */
 static DECLARE_WAIT_QUEUE_HEAD(module_wq);
@@ -903,6 +904,36 @@ static ssize_t show_refcnt(struct module_attribute *mattr,
 static struct module_attribute modinfo_refcnt =
        __ATTR(refcnt, 0444, show_refcnt, NULL);
 
+void __module_get(struct module *module)
+{
+       if (module) {
+               preempt_disable();
+               __this_cpu_inc(module->refptr->incs);
+               trace_module_get(module, _RET_IP_);
+               preempt_enable();
+       }
+}
+EXPORT_SYMBOL(__module_get);
+
+bool try_module_get(struct module *module)
+{
+       bool ret = true;
+
+       if (module) {
+               preempt_disable();
+
+               if (likely(module_is_live(module))) {
+                       __this_cpu_inc(module->refptr->incs);
+                       trace_module_get(module, _RET_IP_);
+               } else
+                       ret = false;
+
+               preempt_enable();
+       }
+       return ret;
+}
+EXPORT_SYMBOL(try_module_get);
+
 void module_put(struct module *module)
 {
        if (module) {
@@ -2380,8 +2411,7 @@ static int copy_and_check(struct load_info *info,
                return -ENOEXEC;
 
        /* Suck in entire file: we'll want most of it. */
-       /* vmalloc barfs on "unusual" numbers.  Check here */
-       if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
+       if ((hdr = vmalloc(len)) == NULL)
                return -ENOMEM;
 
        if (copy_from_user(hdr, umod, len) != 0) {
@@ -2922,7 +2952,8 @@ static struct module *load_module(void __user *umod,
        mutex_unlock(&module_mutex);
 
        /* Module is ready to execute: parsing args may do that. */
-       err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
+       err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
+                        -32768, 32767, NULL);
        if (err < 0)
                goto unlink;
 
index 47f5bf12434a5c20a12a65d5b792b8dce1159c75..f37d82631347187b838dd772913fc875c8cc164e 100644 (file)
@@ -87,6 +87,8 @@ static int parse_one(char *param,
                     char *val,
                     const struct kernel_param *params,
                     unsigned num_params,
+                    s16 min_level,
+                    s16 max_level,
                     int (*handle_unknown)(char *param, char *val))
 {
        unsigned int i;
@@ -95,6 +97,9 @@ static int parse_one(char *param,
        /* Find parameter */
        for (i = 0; i < num_params; i++) {
                if (parameq(param, params[i].name)) {
+                       if (params[i].level < min_level
+                           || params[i].level > max_level)
+                               return 0;
                        /* No one handled NULL, so do it here. */
                        if (!val && params[i].ops->set != param_set_bool
                            && params[i].ops->set != param_set_bint)
@@ -174,6 +179,8 @@ int parse_args(const char *name,
               char *args,
               const struct kernel_param *params,
               unsigned num,
+              s16 min_level,
+              s16 max_level,
               int (*unknown)(char *param, char *val))
 {
        char *param, *val;
@@ -189,7 +196,8 @@ int parse_args(const char *name,
 
                args = next_arg(args, &param, &val);
                irq_was_disabled = irqs_disabled();
-               ret = parse_one(param, val, params, num, unknown);
+               ret = parse_one(param, val, params, num,
+                               min_level, max_level, unknown);
                if (irq_was_disabled && !irqs_disabled()) {
                        printk(KERN_WARNING "parse_args(): option '%s' enabled "
                                        "irq's!\n", param);
@@ -297,35 +305,18 @@ EXPORT_SYMBOL(param_ops_charp);
 /* Actually could be a bool or an int, for historical reasons. */
 int param_set_bool(const char *val, const struct kernel_param *kp)
 {
-       bool v;
-       int ret;
-
        /* No equals means "set"... */
        if (!val) val = "1";
 
        /* One of =[yYnN01] */
-       ret = strtobool(val, &v);
-       if (ret)
-               return ret;
-
-       if (kp->flags & KPARAM_ISBOOL)
-               *(bool *)kp->arg = v;
-       else
-               *(int *)kp->arg = v;
-       return 0;
+       return strtobool(val, kp->arg);
 }
 EXPORT_SYMBOL(param_set_bool);
 
 int param_get_bool(char *buffer, const struct kernel_param *kp)
 {
-       bool val;
-       if (kp->flags & KPARAM_ISBOOL)
-               val = *(bool *)kp->arg;
-       else
-               val = *(int *)kp->arg;
-
        /* Y and N chosen as being relatively non-coder friendly */
-       return sprintf(buffer, "%c", val ? 'Y' : 'N');
+       return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
 }
 EXPORT_SYMBOL(param_get_bool);
 
@@ -343,7 +334,6 @@ int param_set_invbool(const char *val, const struct kernel_param *kp)
        struct kernel_param dummy;
 
        dummy.arg = &boolval;
-       dummy.flags = KPARAM_ISBOOL;
        ret = param_set_bool(val, &dummy);
        if (ret == 0)
                *(bool *)kp->arg = !boolval;
@@ -372,7 +362,6 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
        /* Match bool exactly, by re-using it. */
        boolkp = *kp;
        boolkp.arg = &v;
-       boolkp.flags |= KPARAM_ISBOOL;
 
        ret = param_set_bool(val, &boolkp);
        if (ret == 0)
@@ -393,7 +382,7 @@ static int param_array(const char *name,
                       unsigned int min, unsigned int max,
                       void *elem, int elemsize,
                       int (*set)(const char *, const struct kernel_param *kp),
-                      u16 flags,
+                      s16 level,
                       unsigned int *num)
 {
        int ret;
@@ -403,7 +392,7 @@ static int param_array(const char *name,
        /* Get the name right for errors. */
        kp.name = name;
        kp.arg = elem;
-       kp.flags = flags;
+       kp.level = level;
 
        *num = 0;
        /* We expect a comma-separated list of values. */
@@ -444,7 +433,7 @@ static int param_array_set(const char *val, const struct kernel_param *kp)
        unsigned int temp_num;
 
        return param_array(kp->name, val, 1, arr->max, arr->elem,
-                          arr->elemsize, arr->ops->set, kp->flags,
+                          arr->elemsize, arr->ops->set, kp->level,
                           arr->num ?: &temp_num);
 }
 
index 17b232869a04efce1ac4d43f9c30a66869c470ee..57bc1fd35b3cbe6bffdbfe71af5f13fc00648b81 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/acct.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/reboot.h>
 
 #define BITS_PER_PAGE          (PAGE_SIZE*8)
 
@@ -183,6 +184,9 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
                rc = sys_wait4(-1, NULL, __WALL, NULL);
        } while (rc != -ECHILD);
 
+       if (pid_ns->reboot)
+               current->signal->group_exit_code = pid_ns->reboot;
+
        acct_exit_ns(pid_ns);
        return;
 }
@@ -217,6 +221,35 @@ static struct ctl_table pid_ns_ctl_table[] = {
 
 static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } };
 
+int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
+{
+       if (pid_ns == &init_pid_ns)
+               return 0;
+
+       switch (cmd) {
+       case LINUX_REBOOT_CMD_RESTART2:
+       case LINUX_REBOOT_CMD_RESTART:
+               pid_ns->reboot = SIGHUP;
+               break;
+
+       case LINUX_REBOOT_CMD_POWER_OFF:
+       case LINUX_REBOOT_CMD_HALT:
+               pid_ns->reboot = SIGINT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       read_lock(&tasklist_lock);
+       force_sig(SIGKILL, pid_ns->child_reaper);
+       read_unlock(&tasklist_lock);
+
+       do_exit(0);
+
+       /* Not reached */
+       return 0;
+}
+
 static __init int pid_namespaces_init(void)
 {
        pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
index b152f74f02de3d211c5bc4fb0effbe3ce771c528..6850f53e02d82e023954df56f5230b4033e80b73 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/export.h>
 #include <linux/rwsem.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 
 /*
index 503d6426126d0af026995ff45b8508155dc9c743..e3ed0ecee7c7a47c2b8c85e3717b3606343c30aa 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/init_task.h>
 #include <linux/binfmts.h>
 
+#include <asm/switch_to.h>
 #include <asm/tlb.h>
 #include <asm/irq_regs.h>
 #include <asm/mutex.h>
@@ -1264,29 +1265,59 @@ EXPORT_SYMBOL_GPL(kick_process);
  */
 static int select_fallback_rq(int cpu, struct task_struct *p)
 {
-       int dest_cpu;
        const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(cpu));
+       enum { cpuset, possible, fail } state = cpuset;
+       int dest_cpu;
 
        /* Look for allowed, online CPU in same node. */
-       for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
+       for_each_cpu_mask(dest_cpu, *nodemask) {
+               if (!cpu_online(dest_cpu))
+                       continue;
+               if (!cpu_active(dest_cpu))
+                       continue;
                if (cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p)))
                        return dest_cpu;
+       }
 
-       /* Any allowed, online CPU? */
-       dest_cpu = cpumask_any_and(tsk_cpus_allowed(p), cpu_active_mask);
-       if (dest_cpu < nr_cpu_ids)
-               return dest_cpu;
+       for (;;) {
+               /* Any allowed, online CPU? */
+               for_each_cpu_mask(dest_cpu, *tsk_cpus_allowed(p)) {
+                       if (!cpu_online(dest_cpu))
+                               continue;
+                       if (!cpu_active(dest_cpu))
+                               continue;
+                       goto out;
+               }
 
-       /* No more Mr. Nice Guy. */
-       dest_cpu = cpuset_cpus_allowed_fallback(p);
-       /*
-        * Don't tell them about moving exiting tasks or
-        * kernel threads (both mm NULL), since they never
-        * leave kernel.
-        */
-       if (p->mm && printk_ratelimit()) {
-               printk_sched("process %d (%s) no longer affine to cpu%d\n",
-                               task_pid_nr(p), p->comm, cpu);
+               switch (state) {
+               case cpuset:
+                       /* No more Mr. Nice Guy. */
+                       cpuset_cpus_allowed_fallback(p);
+                       state = possible;
+                       break;
+
+               case possible:
+                       do_set_cpus_allowed(p, cpu_possible_mask);
+                       state = fail;
+                       break;
+
+               case fail:
+                       BUG();
+                       break;
+               }
+       }
+
+out:
+       if (state != cpuset) {
+               /*
+                * Don't tell them about moving exiting tasks or
+                * kernel threads (both mm NULL), since they never
+                * leave kernel.
+                */
+               if (p->mm && printk_ratelimit()) {
+                       printk_sched("process %d (%s) no longer affine to cpu%d\n",
+                                       task_pid_nr(p), p->comm, cpu);
+               }
        }
 
        return dest_cpu;
index 94340c7544a9ad2441d7fd1f6df092c35c0bb6c2..0d97ebdc58f078f821a59c29965509a5e47f02f5 100644 (file)
@@ -416,8 +416,8 @@ find_matching_se(struct sched_entity **se, struct sched_entity **pse)
 
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
-static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                  unsigned long delta_exec);
+static __always_inline
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec);
 
 /**************************************************************
  * Scheduling class tree data structure manipulation methods:
@@ -1162,7 +1162,7 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
                __clear_buddies_skip(se);
 }
 
-static void return_cfs_rq_runtime(struct cfs_rq *cfs_rq);
+static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq);
 
 static void
 dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
@@ -1546,8 +1546,8 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
                resched_task(rq_of(cfs_rq)->curr);
 }
 
-static __always_inline void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                                  unsigned long delta_exec)
+static __always_inline
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec)
 {
        if (!cfs_bandwidth_used() || !cfs_rq->runtime_enabled)
                return;
@@ -2073,11 +2073,11 @@ void unthrottle_offline_cfs_rqs(struct rq *rq)
 }
 
 #else /* CONFIG_CFS_BANDWIDTH */
-static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec) {}
+static __always_inline
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec) {}
 static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
-static void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
+static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 
 static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq)
 {
index b60dad720173e6f396eb9216dc81d85cf8b5fdf0..44af55e6d5d0ffcea0691ad28b800c24b9567696 100644 (file)
@@ -1428,7 +1428,7 @@ static struct task_struct *pick_next_highest_task_rt(struct rq *rq, int cpu)
 next_idx:
                if (idx >= MAX_RT_PRIO)
                        continue;
-               if (next && next->prio < idx)
+               if (next && next->prio <= idx)
                        continue;
                list_for_each_entry(rt_se, array->queue + idx, run_list) {
                        struct task_struct *p;
index d523da02dd14011188649e401de4ac36eaf43a58..17afcaf582d07a5bb8abf843a44d1f593403e473 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
+#include <asm/cacheflush.h>
 #include "audit.h"     /* audit_signal_info() */
 
 /*
index db197d60489b7c144f2f44fbea00e15944e31871..2f8b10ecf75996c1bf40feb78bf2a0c1d5471489 100644 (file)
@@ -701,3 +701,93 @@ int on_each_cpu(void (*func) (void *info), void *info, int wait)
        return ret;
 }
 EXPORT_SYMBOL(on_each_cpu);
+
+/**
+ * on_each_cpu_mask(): Run a function on processors specified by
+ * cpumask, which may include the local processor.
+ * @mask: The set of cpus to run on (only runs on online subset).
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @wait: If true, wait (atomically) until function has completed
+ *        on other CPUs.
+ *
+ * If @wait is true, then returns once @func has returned.
+ *
+ * You must not call this function with disabled interrupts or
+ * from a hardware interrupt handler or from a bottom half handler.
+ */
+void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
+                       void *info, bool wait)
+{
+       int cpu = get_cpu();
+
+       smp_call_function_many(mask, func, info, wait);
+       if (cpumask_test_cpu(cpu, mask)) {
+               local_irq_disable();
+               func(info);
+               local_irq_enable();
+       }
+       put_cpu();
+}
+EXPORT_SYMBOL(on_each_cpu_mask);
+
+/*
+ * on_each_cpu_cond(): Call a function on each processor for which
+ * the supplied function cond_func returns true, optionally waiting
+ * for all the required CPUs to finish. This may include the local
+ * processor.
+ * @cond_func: A callback function that is passed a cpu id and
+ *             the the info parameter. The function is called
+ *             with preemption disabled. The function should
+ *             return a blooean value indicating whether to IPI
+ *             the specified CPU.
+ * @func:      The function to run on all applicable CPUs.
+ *             This must be fast and non-blocking.
+ * @info:      An arbitrary pointer to pass to both functions.
+ * @wait:      If true, wait (atomically) until function has
+ *             completed on other CPUs.
+ * @gfp_flags: GFP flags to use when allocating the cpumask
+ *             used internally by the function.
+ *
+ * The function might sleep if the GFP flags indicates a non
+ * atomic allocation is allowed.
+ *
+ * Preemption is disabled to protect against CPUs going offline but not online.
+ * CPUs going online during the call will not be seen or sent an IPI.
+ *
+ * You must not call this function with disabled interrupts or
+ * from a hardware interrupt handler or from a bottom half handler.
+ */
+void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
+                       smp_call_func_t func, void *info, bool wait,
+                       gfp_t gfp_flags)
+{
+       cpumask_var_t cpus;
+       int cpu, ret;
+
+       might_sleep_if(gfp_flags & __GFP_WAIT);
+
+       if (likely(zalloc_cpumask_var(&cpus, (gfp_flags|__GFP_NOWARN)))) {
+               preempt_disable();
+               for_each_online_cpu(cpu)
+                       if (cond_func(cpu, info))
+                               cpumask_set_cpu(cpu, cpus);
+               on_each_cpu_mask(cpus, func, info, wait);
+               preempt_enable();
+               free_cpumask_var(cpus);
+       } else {
+               /*
+                * No free cpumask, bother. No matter, we'll
+                * just have to IPI them one by one.
+                */
+               preempt_disable();
+               for_each_online_cpu(cpu)
+                       if (cond_func(cpu, info)) {
+                               ret = smp_call_function_single(cpu, func,
+                                                               info, wait);
+                               WARN_ON_ONCE(!ret);
+                       }
+               preempt_enable();
+       }
+}
+EXPORT_SYMBOL(on_each_cpu_cond);
index 84c7d96918bf44b8b155d4c72afbd35e6a3bd6cd..5cdd8065a3ce32f6cecadd5a99a59a8ebc937613 100644 (file)
@@ -163,7 +163,7 @@ void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock)
 EXPORT_SYMBOL(_raw_spin_lock_bh);
 #endif
 
-#ifndef CONFIG_INLINE_SPIN_UNLOCK
+#ifdef CONFIG_UNINLINE_SPIN_UNLOCK
 void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock)
 {
        __raw_spin_unlock(lock);
index 9eb7fcab8df622cdc1ad7fa032963324b777e982..e7006eb6c1e4fdc3fa7967eaa45541609b5d499f 100644 (file)
@@ -444,6 +444,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
                        magic2 != LINUX_REBOOT_MAGIC2C))
                return -EINVAL;
 
+       /*
+        * If pid namespaces are enabled and the current task is in a child
+        * pid_namespace, the command is handled by reboot_pid_ns() which will
+        * call do_exit().
+        */
+       ret = reboot_pid_ns(task_active_pid_ns(current), cmd);
+       if (ret)
+               return ret;
+
        /* Instead of trying to make the power_off code look like
         * halt when pm_power_off is not set do it the easy way.
         */
index d48ff4fd44c328eb3458390b79facac08734b7b9..52b3a06a02f8406c4f78eb06cfaad89f51910a21 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/bitmap.h>
 #include <linux/signal.h>
 #include <linux/printk.h>
 #include <linux/proc_fs.h>
@@ -68,6 +69,9 @@
 #include <asm/stacktrace.h>
 #include <asm/io.h>
 #endif
+#ifdef CONFIG_SPARC
+#include <asm/setup.h>
+#endif
 #ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
 #endif
@@ -142,7 +146,6 @@ static const int cap_last_cap = CAP_LAST_CAP;
 #include <linux/inotify.h>
 #endif
 #ifdef CONFIG_SPARC
-#include <asm/system.h>
 #endif
 
 #ifdef CONFIG_SPARC64
@@ -2393,9 +2396,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                                }
                        }
 
-                       while (val_a <= val_b)
-                               set_bit(val_a++, tmp_bitmap);
-
+                       bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
                        first = 0;
                        proc_skip_char(&kbuf, &left, '\n');
                }
@@ -2438,8 +2439,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                        if (*ppos)
                                bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
                        else
-                               memcpy(bitmap, tmp_bitmap,
-                                       BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long));
+                               bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
                }
                kfree(tmp_bitmap);
                *lenp -= left;
index 73e416db0a1e6b23205cc416864ea2c91b9d26d0..ba744cf80696203b65406c7aef8faae3a23048d0 100644 (file)
@@ -163,7 +163,6 @@ int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
                return error;
 
        if (tz) {
-               /* SMP safe, global irq locking makes it work. */
                sys_tz = *tz;
                update_vsyscall_tz();
                if (firsttime) {
@@ -173,12 +172,7 @@ int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
                }
        }
        if (tv)
-       {
-               /* SMP safe, again the code in arch/foo/time.c should
-                * globally block out interrupts when it runs.
-                */
                return do_settimeofday(tv);
-       }
        return 0;
 }
 
index 8a46f5d64504f15dcaf31ec4f5fcee7ea15a8bdf..8a538c55fc7be401031dc5b2bf5a072dd5a03a0b 100644 (file)
@@ -96,6 +96,11 @@ static int alarmtimer_rtc_add_device(struct device *dev,
        return 0;
 }
 
+static inline void alarmtimer_rtc_timer_init(void)
+{
+       rtc_timer_init(&rtctimer, NULL, NULL);
+}
+
 static struct class_interface alarmtimer_rtc_interface = {
        .add_dev = &alarmtimer_rtc_add_device,
 };
@@ -117,6 +122,7 @@ static inline struct rtc_device *alarmtimer_get_rtcdev(void)
 #define rtcdev (NULL)
 static inline int alarmtimer_rtc_interface_setup(void) { return 0; }
 static inline void alarmtimer_rtc_interface_remove(void) { }
+static inline void alarmtimer_rtc_timer_init(void) { }
 #endif
 
 /**
@@ -783,6 +789,8 @@ static int __init alarmtimer_init(void)
                .nsleep         = alarm_timer_nsleep,
        };
 
+       alarmtimer_rtc_timer_init();
+
        posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
        posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
 
index a45ca167ab242070577b874f16fe004735b8de07..c9583382141a439ce10980bfc399792e8c6f8423 100644 (file)
@@ -500,7 +500,7 @@ static u32 clocksource_max_adjustment(struct clocksource *cs)
 {
        u64 ret;
        /*
-        * We won't try to correct for more then 11% adjustments (110,000 ppm),
+        * We won't try to correct for more than 11% adjustments (110,000 ppm),
         */
        ret = (u64)cs->mult * 11;
        do_div(ret,100);
index 6e039b144daf0359ecaffcbc00227a7233fd0dd3..f03fd83b170b7176bbfe32c1589ce4fdec5e07bb 100644 (file)
@@ -34,8 +34,6 @@ unsigned long                 tick_nsec;
 static u64                     tick_length;
 static u64                     tick_length_base;
 
-static struct hrtimer          leap_timer;
-
 #define MAX_TICKADJ            500LL           /* usecs */
 #define MAX_TICKADJ_SCALED \
        (((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
@@ -381,70 +379,63 @@ u64 ntp_tick_length(void)
 
 
 /*
- * Leap second processing. If in leap-insert state at the end of the
- * day, the system clock is set back one second; if in leap-delete
- * state, the system clock is set ahead one second.
+ * this routine handles the overflow of the microsecond field
+ *
+ * The tricky bits of code to handle the accurate clock support
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+ * They were originally developed for SUN and DEC kernels.
+ * All the kudos should go to Dave for this stuff.
+ *
+ * Also handles leap second processing, and returns leap offset
  */
-static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
+int second_overflow(unsigned long secs)
 {
-       enum hrtimer_restart res = HRTIMER_NORESTART;
-       unsigned long flags;
+       s64 delta;
        int leap = 0;
+       unsigned long flags;
 
        spin_lock_irqsave(&ntp_lock, flags);
+
+       /*
+        * Leap second processing. If in leap-insert state at the end of the
+        * day, the system clock is set back one second; if in leap-delete
+        * state, the system clock is set ahead one second.
+        */
        switch (time_state) {
        case TIME_OK:
+               if (time_status & STA_INS)
+                       time_state = TIME_INS;
+               else if (time_status & STA_DEL)
+                       time_state = TIME_DEL;
                break;
        case TIME_INS:
-               leap = -1;
-               time_state = TIME_OOP;
-               printk(KERN_NOTICE
-                       "Clock: inserting leap second 23:59:60 UTC\n");
-               hrtimer_add_expires_ns(&leap_timer, NSEC_PER_SEC);
-               res = HRTIMER_RESTART;
+               if (secs % 86400 == 0) {
+                       leap = -1;
+                       time_state = TIME_OOP;
+                       printk(KERN_NOTICE
+                               "Clock: inserting leap second 23:59:60 UTC\n");
+               }
                break;
        case TIME_DEL:
-               leap = 1;
-               time_tai--;
-               time_state = TIME_WAIT;
-               printk(KERN_NOTICE
-                       "Clock: deleting leap second 23:59:59 UTC\n");
+               if ((secs + 1) % 86400 == 0) {
+                       leap = 1;
+                       time_tai--;
+                       time_state = TIME_WAIT;
+                       printk(KERN_NOTICE
+                               "Clock: deleting leap second 23:59:59 UTC\n");
+               }
                break;
        case TIME_OOP:
                time_tai++;
                time_state = TIME_WAIT;
-               /* fall through */
+               break;
+
        case TIME_WAIT:
                if (!(time_status & (STA_INS | STA_DEL)))
                        time_state = TIME_OK;
                break;
        }
-       spin_unlock_irqrestore(&ntp_lock, flags);
 
-       /*
-        * We have to call this outside of the ntp_lock to keep
-        * the proper locking hierarchy
-        */
-       if (leap)
-               timekeeping_leap_insert(leap);
-
-       return res;
-}
-
-/*
- * this routine handles the overflow of the microsecond field
- *
- * The tricky bits of code to handle the accurate clock support
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
- * They were originally developed for SUN and DEC kernels.
- * All the kudos should go to Dave for this stuff.
- */
-void second_overflow(void)
-{
-       s64 delta;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ntp_lock, flags);
 
        /* Bump the maxerror field */
        time_maxerror += MAXFREQ / NSEC_PER_USEC;
@@ -481,15 +472,17 @@ void second_overflow(void)
        tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
                                                         << NTP_SCALE_SHIFT;
        time_adjust = 0;
+
+
+
 out:
        spin_unlock_irqrestore(&ntp_lock, flags);
+
+       return leap;
 }
 
 #ifdef CONFIG_GENERIC_CMOS_UPDATE
 
-/* Disable the cmos update - used by virtualization and embedded */
-int no_sync_cmos_clock  __read_mostly;
-
 static void sync_cmos_clock(struct work_struct *work);
 
 static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock);
@@ -536,35 +529,13 @@ static void sync_cmos_clock(struct work_struct *work)
 
 static void notify_cmos_timer(void)
 {
-       if (!no_sync_cmos_clock)
-               schedule_delayed_work(&sync_cmos_work, 0);
+       schedule_delayed_work(&sync_cmos_work, 0);
 }
 
 #else
 static inline void notify_cmos_timer(void) { }
 #endif
 
-/*
- * Start the leap seconds timer:
- */
-static inline void ntp_start_leap_timer(struct timespec *ts)
-{
-       long now = ts->tv_sec;
-
-       if (time_status & STA_INS) {
-               time_state = TIME_INS;
-               now += 86400 - now % 86400;
-               hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
-
-               return;
-       }
-
-       if (time_status & STA_DEL) {
-               time_state = TIME_DEL;
-               now += 86400 - (now + 1) % 86400;
-               hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
-       }
-}
 
 /*
  * Propagate a new txc->status value into the NTP state:
@@ -589,22 +560,6 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
        time_status &= STA_RONLY;
        time_status |= txc->status & ~STA_RONLY;
 
-       switch (time_state) {
-       case TIME_OK:
-               ntp_start_leap_timer(ts);
-               break;
-       case TIME_INS:
-       case TIME_DEL:
-               time_state = TIME_OK;
-               ntp_start_leap_timer(ts);
-       case TIME_WAIT:
-               if (!(time_status & (STA_INS | STA_DEL)))
-                       time_state = TIME_OK;
-               break;
-       case TIME_OOP:
-               hrtimer_restart(&leap_timer);
-               break;
-       }
 }
 /*
  * Called with the xtime lock held, so we can access and modify
@@ -686,9 +641,6 @@ int do_adjtimex(struct timex *txc)
                    (txc->tick <  900000/USER_HZ ||
                     txc->tick > 1100000/USER_HZ))
                        return -EINVAL;
-
-               if (txc->modes & ADJ_STATUS && time_state != TIME_OK)
-                       hrtimer_cancel(&leap_timer);
        }
 
        if (txc->modes & ADJ_SETOFFSET) {
@@ -1010,6 +962,4 @@ __setup("ntp_tick_adj=", ntp_tick_adj_setup);
 void __init ntp_init(void)
 {
        ntp_clear();
-       hrtimer_init(&leap_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
-       leap_timer.function = ntp_leap_second;
 }
index 15be32e19c6e916dd2b52c29bac9d2b93f9cdef8..d66b21308f7c10639c9da150ee69e3f3dc332e47 100644 (file)
@@ -184,18 +184,6 @@ static void timekeeping_update(bool clearntp)
 }
 
 
-void timekeeping_leap_insert(int leapsecond)
-{
-       unsigned long flags;
-
-       write_seqlock_irqsave(&timekeeper.lock, flags);
-       timekeeper.xtime.tv_sec += leapsecond;
-       timekeeper.wall_to_monotonic.tv_sec -= leapsecond;
-       timekeeping_update(false);
-       write_sequnlock_irqrestore(&timekeeper.lock, flags);
-
-}
-
 /**
  * timekeeping_forward_now - update clock to the current time
  *
@@ -448,9 +436,12 @@ EXPORT_SYMBOL(timekeeping_inject_offset);
 static int change_clocksource(void *data)
 {
        struct clocksource *new, *old;
+       unsigned long flags;
 
        new = (struct clocksource *) data;
 
+       write_seqlock_irqsave(&timekeeper.lock, flags);
+
        timekeeping_forward_now();
        if (!new->enable || new->enable(new) == 0) {
                old = timekeeper.clock;
@@ -458,6 +449,10 @@ static int change_clocksource(void *data)
                if (old->disable)
                        old->disable(old);
        }
+       timekeeping_update(true);
+
+       write_sequnlock_irqrestore(&timekeeper.lock, flags);
+
        return 0;
 }
 
@@ -827,7 +822,7 @@ static void timekeeping_adjust(s64 offset)
        int adj;
 
        /*
-        * The point of this is to check if the error is greater then half
+        * The point of this is to check if the error is greater than half
         * an interval.
         *
         * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs.
@@ -835,7 +830,7 @@ static void timekeeping_adjust(s64 offset)
         * Note we subtract one in the shift, so that error is really error*2.
         * This "saves" dividing(shifting) interval twice, but keeps the
         * (error > interval) comparison as still measuring if error is
-        * larger then half an interval.
+        * larger than half an interval.
         *
         * Note: It does not "save" on aggravation when reading the code.
         */
@@ -843,7 +838,7 @@ static void timekeeping_adjust(s64 offset)
        if (error > interval) {
                /*
                 * We now divide error by 4(via shift), which checks if
-                * the error is greater then twice the interval.
+                * the error is greater than twice the interval.
                 * If it is greater, we need a bigadjust, if its smaller,
                 * we can adjust by 1.
                 */
@@ -874,13 +869,15 @@ static void timekeeping_adjust(s64 offset)
        } else /* No adjustment needed */
                return;
 
-       WARN_ONCE(timekeeper.clock->maxadj &&
-                       (timekeeper.mult + adj > timekeeper.clock->mult +
-                                               timekeeper.clock->maxadj),
-                       "Adjusting %s more then 11%% (%ld vs %ld)\n",
+       if (unlikely(timekeeper.clock->maxadj &&
+                       (timekeeper.mult + adj >
+                       timekeeper.clock->mult + timekeeper.clock->maxadj))) {
+               printk_once(KERN_WARNING
+                       "Adjusting %s more than 11%% (%ld vs %ld)\n",
                        timekeeper.clock->name, (long)timekeeper.mult + adj,
                        (long)timekeeper.clock->mult +
                                timekeeper.clock->maxadj);
+       }
        /*
         * So the following can be confusing.
         *
@@ -952,7 +949,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
        u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift;
        u64 raw_nsecs;
 
-       /* If the offset is smaller then a shifted interval, do nothing */
+       /* If the offset is smaller than a shifted interval, do nothing */
        if (offset < timekeeper.cycle_interval<<shift)
                return offset;
 
@@ -962,9 +959,11 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
 
        timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
        while (timekeeper.xtime_nsec >= nsecps) {
+               int leap;
                timekeeper.xtime_nsec -= nsecps;
                timekeeper.xtime.tv_sec++;
-               second_overflow();
+               leap = second_overflow(timekeeper.xtime.tv_sec);
+               timekeeper.xtime.tv_sec += leap;
        }
 
        /* Accumulate raw time */
@@ -1018,13 +1017,13 @@ static void update_wall_time(void)
         * With NO_HZ we may have to accumulate many cycle_intervals
         * (think "ticks") worth of time at once. To do this efficiently,
         * we calculate the largest doubling multiple of cycle_intervals
-        * that is smaller then the offset. We then accumulate that
+        * that is smaller than the offset.  We then accumulate that
         * chunk in one go, and then try to consume the next smaller
         * doubled multiple.
         */
        shift = ilog2(offset) - ilog2(timekeeper.cycle_interval);
        shift = max(0, shift);
-       /* Bound shift to one less then what overflows tick_length */
+       /* Bound shift to one less than what overflows tick_length */
        maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
        shift = min(shift, maxshift);
        while (offset >= timekeeper.cycle_interval) {
@@ -1072,12 +1071,14 @@ static void update_wall_time(void)
 
        /*
         * Finally, make sure that after the rounding
-        * xtime.tv_nsec isn't larger then NSEC_PER_SEC
+        * xtime.tv_nsec isn't larger than NSEC_PER_SEC
         */
        if (unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC)) {
+               int leap;
                timekeeper.xtime.tv_nsec -= NSEC_PER_SEC;
                timekeeper.xtime.tv_sec++;
-               second_overflow();
+               leap = second_overflow(timekeeper.xtime.tv_sec);
+               timekeeper.xtime.tv_sec += leap;
        }
 
        timekeeping_update(false);
index a0e5900a9d85eedba0da1420836797476753f8a0..4a8aba2e5cc016b84776a85af19d8d2d1b404f30 100644 (file)
@@ -88,6 +88,10 @@ choice
        prompt "CRC32 implementation"
        depends on CRC32
        default CRC32_SLICEBY8
+       help
+         This option allows a kernel builder to override the default choice
+         of CRC32 algorithm.  Choose the default ("slice by 8") unless you
+         know that you need one of the others.
 
 config CRC32_SLICEBY8
        bool "Slice by 8 bytes"
index f7af95d304c503eb4b5ca71ea4c6912656e663fa..6777153f18f31c3318b94283e986b5f2866ad783 100644 (file)
@@ -499,6 +499,7 @@ config RT_MUTEX_TESTER
 config DEBUG_SPINLOCK
        bool "Spinlock and rw-lock debugging: basic checks"
        depends on DEBUG_KERNEL
+       select UNINLINE_SPIN_UNLOCK
        help
          Say Y here and build SMP to catch missing spinlock initialization
          and certain other kinds of spinlock errors commonly made.  This is
index 0b660118ed91d1323140b5cf1a503ee44ecb3aa6..402a54ac35cbf60f665485ddd18500d5034e9ee9 100644 (file)
@@ -26,18 +26,6 @@ int __next_cpu_nr(int n, const cpumask_t *srcp)
 EXPORT_SYMBOL(__next_cpu_nr);
 #endif
 
-int __any_online_cpu(const cpumask_t *mask)
-{
-       int cpu;
-
-       for_each_cpu(cpu, mask) {
-               if (cpu_online(cpu))
-                       break;
-       }
-       return cpu;
-}
-EXPORT_SYMBOL(__any_online_cpu);
-
 /**
  * cpumask_next_and - get the next cpu in *src1p & *src2p
  * @n: the cpu prior to the place to search (ie. return will be > @n)
index 8221b3d2fbf0dc1f5356de339ed6c70071ba0a1f..4a15115e90f84190524618eb2cf5d55c7684dd86 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/interrupt.h>
 #include <linux/llist.h>
 
-#include <asm/system.h>
 
 /**
  * llist_add_batch - add several linked entries in batch
index 3e69c2b66c9454cd074a9649ff946598467ba407..86516f5588e31782676087fd49fe45fd87538c03 100644 (file)
@@ -3,6 +3,7 @@
  * Portions Copyright (C) 2001 Christoph Hellwig
  * Copyright (C) 2005 SGI, Christoph Lameter
  * Copyright (C) 2006 Nick Piggin
+ * Copyright (C) 2012 Konstantin Khlebnikov
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -146,6 +147,43 @@ static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag)
        }
        return 0;
 }
+
+/**
+ * radix_tree_find_next_bit - find the next set bit in a memory region
+ *
+ * @addr: The address to base the search on
+ * @size: The bitmap size in bits
+ * @offset: The bitnumber to start searching at
+ *
+ * Unrollable variant of find_next_bit() for constant size arrays.
+ * Tail bits starting from size to roundup(size, BITS_PER_LONG) must be zero.
+ * Returns next bit offset, or size if nothing found.
+ */
+static __always_inline unsigned long
+radix_tree_find_next_bit(const unsigned long *addr,
+                        unsigned long size, unsigned long offset)
+{
+       if (!__builtin_constant_p(size))
+               return find_next_bit(addr, size, offset);
+
+       if (offset < size) {
+               unsigned long tmp;
+
+               addr += offset / BITS_PER_LONG;
+               tmp = *addr >> (offset % BITS_PER_LONG);
+               if (tmp)
+                       return __ffs(tmp) + offset;
+               offset = (offset + BITS_PER_LONG) & ~(BITS_PER_LONG - 1);
+               while (offset < size) {
+                       tmp = *++addr;
+                       if (tmp)
+                               return __ffs(tmp) + offset;
+                       offset += BITS_PER_LONG;
+               }
+       }
+       return size;
+}
+
 /*
  * This assumes that the caller has performed appropriate preallocation, and
  * that the caller has pinned this thread of control to the current CPU.
@@ -612,6 +650,119 @@ int radix_tree_tag_get(struct radix_tree_root *root,
 }
 EXPORT_SYMBOL(radix_tree_tag_get);
 
+/**
+ * radix_tree_next_chunk - find next chunk of slots for iteration
+ *
+ * @root:      radix tree root
+ * @iter:      iterator state
+ * @flags:     RADIX_TREE_ITER_* flags and tag index
+ * Returns:    pointer to chunk first slot, or NULL if iteration is over
+ */
+void **radix_tree_next_chunk(struct radix_tree_root *root,
+                            struct radix_tree_iter *iter, unsigned flags)
+{
+       unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK;
+       struct radix_tree_node *rnode, *node;
+       unsigned long index, offset;
+
+       if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
+               return NULL;
+
+       /*
+        * Catch next_index overflow after ~0UL. iter->index never overflows
+        * during iterating; it can be zero only at the beginning.
+        * And we cannot overflow iter->next_index in a single step,
+        * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.
+        */
+       index = iter->next_index;
+       if (!index && iter->index)
+               return NULL;
+
+       rnode = rcu_dereference_raw(root->rnode);
+       if (radix_tree_is_indirect_ptr(rnode)) {
+               rnode = indirect_to_ptr(rnode);
+       } else if (rnode && !index) {
+               /* Single-slot tree */
+               iter->index = 0;
+               iter->next_index = 1;
+               iter->tags = 1;
+               return (void **)&root->rnode;
+       } else
+               return NULL;
+
+restart:
+       shift = (rnode->height - 1) * RADIX_TREE_MAP_SHIFT;
+       offset = index >> shift;
+
+       /* Index outside of the tree */
+       if (offset >= RADIX_TREE_MAP_SIZE)
+               return NULL;
+
+       node = rnode;
+       while (1) {
+               if ((flags & RADIX_TREE_ITER_TAGGED) ?
+                               !test_bit(offset, node->tags[tag]) :
+                               !node->slots[offset]) {
+                       /* Hole detected */
+                       if (flags & RADIX_TREE_ITER_CONTIG)
+                               return NULL;
+
+                       if (flags & RADIX_TREE_ITER_TAGGED)
+                               offset = radix_tree_find_next_bit(
+                                               node->tags[tag],
+                                               RADIX_TREE_MAP_SIZE,
+                                               offset + 1);
+                       else
+                               while (++offset < RADIX_TREE_MAP_SIZE) {
+                                       if (node->slots[offset])
+                                               break;
+                               }
+                       index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1);
+                       index += offset << shift;
+                       /* Overflow after ~0UL */
+                       if (!index)
+                               return NULL;
+                       if (offset == RADIX_TREE_MAP_SIZE)
+                               goto restart;
+               }
+
+               /* This is leaf-node */
+               if (!shift)
+                       break;
+
+               node = rcu_dereference_raw(node->slots[offset]);
+               if (node == NULL)
+                       goto restart;
+               shift -= RADIX_TREE_MAP_SHIFT;
+               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+       }
+
+       /* Update the iterator state */
+       iter->index = index;
+       iter->next_index = (index | RADIX_TREE_MAP_MASK) + 1;
+
+       /* Construct iter->tags bit-mask from node->tags[tag] array */
+       if (flags & RADIX_TREE_ITER_TAGGED) {
+               unsigned tag_long, tag_bit;
+
+               tag_long = offset / BITS_PER_LONG;
+               tag_bit  = offset % BITS_PER_LONG;
+               iter->tags = node->tags[tag][tag_long] >> tag_bit;
+               /* This never happens if RADIX_TREE_TAG_LONGS == 1 */
+               if (tag_long < RADIX_TREE_TAG_LONGS - 1) {
+                       /* Pick tags from next element */
+                       if (tag_bit)
+                               iter->tags |= node->tags[tag][tag_long + 1] <<
+                                               (BITS_PER_LONG - tag_bit);
+                       /* Clip chunk size, here only BITS_PER_LONG tags */
+                       iter->next_index = index + BITS_PER_LONG;
+               }
+       }
+
+       return node->slots + offset;
+}
+EXPORT_SYMBOL(radix_tree_next_chunk);
+
 /**
  * radix_tree_range_tag_if_tagged - for each item in given range set given
  *                                tag if item has another tag set
@@ -817,57 +968,6 @@ unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
 }
 EXPORT_SYMBOL(radix_tree_prev_hole);
 
-static unsigned int
-__lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices,
-       unsigned long index, unsigned int max_items, unsigned long *next_index)
-{
-       unsigned int nr_found = 0;
-       unsigned int shift, height;
-       unsigned long i;
-
-       height = slot->height;
-       if (height == 0)
-               goto out;
-       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-
-       for ( ; height > 1; height--) {
-               i = (index >> shift) & RADIX_TREE_MAP_MASK;
-               for (;;) {
-                       if (slot->slots[i] != NULL)
-                               break;
-                       index &= ~((1UL << shift) - 1);
-                       index += 1UL << shift;
-                       if (index == 0)
-                               goto out;       /* 32-bit wraparound */
-                       i++;
-                       if (i == RADIX_TREE_MAP_SIZE)
-                               goto out;
-               }
-
-               shift -= RADIX_TREE_MAP_SHIFT;
-               slot = rcu_dereference_raw(slot->slots[i]);
-               if (slot == NULL)
-                       goto out;
-       }
-
-       /* Bottom level: grab some items */
-       for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
-               if (slot->slots[i]) {
-                       results[nr_found] = &(slot->slots[i]);
-                       if (indices)
-                               indices[nr_found] = index;
-                       if (++nr_found == max_items) {
-                               index++;
-                               goto out;
-                       }
-               }
-               index++;
-       }
-out:
-       *next_index = index;
-       return nr_found;
-}
-
 /**
  *     radix_tree_gang_lookup - perform multiple lookup on a radix tree
  *     @root:          radix tree root
@@ -891,48 +991,19 @@ unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                        unsigned long first_index, unsigned int max_items)
 {
-       unsigned long max_index;
-       struct radix_tree_node *node;
-       unsigned long cur_index = first_index;
-       unsigned int ret;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned int ret = 0;
 
-       node = rcu_dereference_raw(root->rnode);
-       if (!node)
+       if (unlikely(!max_items))
                return 0;
 
-       if (!radix_tree_is_indirect_ptr(node)) {
-               if (first_index > 0)
-                       return 0;
-               results[0] = node;
-               return 1;
-       }
-       node = indirect_to_ptr(node);
-
-       max_index = radix_tree_maxindex(node->height);
-
-       ret = 0;
-       while (ret < max_items) {
-               unsigned int nr_found, slots_found, i;
-               unsigned long next_index;       /* Index of next search */
-
-               if (cur_index > max_index)
-                       break;
-               slots_found = __lookup(node, (void ***)results + ret, NULL,
-                               cur_index, max_items - ret, &next_index);
-               nr_found = 0;
-               for (i = 0; i < slots_found; i++) {
-                       struct radix_tree_node *slot;
-                       slot = *(((void ***)results)[ret + i]);
-                       if (!slot)
-                               continue;
-                       results[ret + nr_found] =
-                               indirect_to_ptr(rcu_dereference_raw(slot));
-                       nr_found++;
-               }
-               ret += nr_found;
-               if (next_index == 0)
+       radix_tree_for_each_slot(slot, root, &iter, first_index) {
+               results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
+               if (!results[ret])
+                       continue;
+               if (++ret == max_items)
                        break;
-               cur_index = next_index;
        }
 
        return ret;
@@ -962,112 +1033,25 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root,
                        void ***results, unsigned long *indices,
                        unsigned long first_index, unsigned int max_items)
 {
-       unsigned long max_index;
-       struct radix_tree_node *node;
-       unsigned long cur_index = first_index;
-       unsigned int ret;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned int ret = 0;
 
-       node = rcu_dereference_raw(root->rnode);
-       if (!node)
+       if (unlikely(!max_items))
                return 0;
 
-       if (!radix_tree_is_indirect_ptr(node)) {
-               if (first_index > 0)
-                       return 0;
-               results[0] = (void **)&root->rnode;
+       radix_tree_for_each_slot(slot, root, &iter, first_index) {
+               results[ret] = slot;
                if (indices)
-                       indices[0] = 0;
-               return 1;
-       }
-       node = indirect_to_ptr(node);
-
-       max_index = radix_tree_maxindex(node->height);
-
-       ret = 0;
-       while (ret < max_items) {
-               unsigned int slots_found;
-               unsigned long next_index;       /* Index of next search */
-
-               if (cur_index > max_index)
+                       indices[ret] = iter.index;
+               if (++ret == max_items)
                        break;
-               slots_found = __lookup(node, results + ret,
-                               indices ? indices + ret : NULL,
-                               cur_index, max_items - ret, &next_index);
-               ret += slots_found;
-               if (next_index == 0)
-                       break;
-               cur_index = next_index;
        }
 
        return ret;
 }
 EXPORT_SYMBOL(radix_tree_gang_lookup_slot);
 
-/*
- * FIXME: the two tag_get()s here should use find_next_bit() instead of
- * open-coding the search.
- */
-static unsigned int
-__lookup_tag(struct radix_tree_node *slot, void ***results, unsigned long index,
-       unsigned int max_items, unsigned long *next_index, unsigned int tag)
-{
-       unsigned int nr_found = 0;
-       unsigned int shift, height;
-
-       height = slot->height;
-       if (height == 0)
-               goto out;
-       shift = (height-1) * RADIX_TREE_MAP_SHIFT;
-
-       while (height > 0) {
-               unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK ;
-
-               for (;;) {
-                       if (tag_get(slot, tag, i))
-                               break;
-                       index &= ~((1UL << shift) - 1);
-                       index += 1UL << shift;
-                       if (index == 0)
-                               goto out;       /* 32-bit wraparound */
-                       i++;
-                       if (i == RADIX_TREE_MAP_SIZE)
-                               goto out;
-               }
-               height--;
-               if (height == 0) {      /* Bottom level: grab some items */
-                       unsigned long j = index & RADIX_TREE_MAP_MASK;
-
-                       for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
-                               index++;
-                               if (!tag_get(slot, tag, j))
-                                       continue;
-                               /*
-                                * Even though the tag was found set, we need to
-                                * recheck that we have a non-NULL node, because
-                                * if this lookup is lockless, it may have been
-                                * subsequently deleted.
-                                *
-                                * Similar care must be taken in any place that
-                                * lookup ->slots[x] without a lock (ie. can't
-                                * rely on its value remaining the same).
-                                */
-                               if (slot->slots[j]) {
-                                       results[nr_found++] = &(slot->slots[j]);
-                                       if (nr_found == max_items)
-                                               goto out;
-                               }
-                       }
-               }
-               shift -= RADIX_TREE_MAP_SHIFT;
-               slot = rcu_dereference_raw(slot->slots[i]);
-               if (slot == NULL)
-                       break;
-       }
-out:
-       *next_index = index;
-       return nr_found;
-}
-
 /**
  *     radix_tree_gang_lookup_tag - perform multiple lookup on a radix tree
  *                                  based on a tag
@@ -1086,52 +1070,19 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
                unsigned long first_index, unsigned int max_items,
                unsigned int tag)
 {
-       struct radix_tree_node *node;
-       unsigned long max_index;
-       unsigned long cur_index = first_index;
-       unsigned int ret;
-
-       /* check the root's tag bit */
-       if (!root_tag_get(root, tag))
-               return 0;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned int ret = 0;
 
-       node = rcu_dereference_raw(root->rnode);
-       if (!node)
+       if (unlikely(!max_items))
                return 0;
 
-       if (!radix_tree_is_indirect_ptr(node)) {
-               if (first_index > 0)
-                       return 0;
-               results[0] = node;
-               return 1;
-       }
-       node = indirect_to_ptr(node);
-
-       max_index = radix_tree_maxindex(node->height);
-
-       ret = 0;
-       while (ret < max_items) {
-               unsigned int nr_found, slots_found, i;
-               unsigned long next_index;       /* Index of next search */
-
-               if (cur_index > max_index)
-                       break;
-               slots_found = __lookup_tag(node, (void ***)results + ret,
-                               cur_index, max_items - ret, &next_index, tag);
-               nr_found = 0;
-               for (i = 0; i < slots_found; i++) {
-                       struct radix_tree_node *slot;
-                       slot = *(((void ***)results)[ret + i]);
-                       if (!slot)
-                               continue;
-                       results[ret + nr_found] =
-                               indirect_to_ptr(rcu_dereference_raw(slot));
-                       nr_found++;
-               }
-               ret += nr_found;
-               if (next_index == 0)
+       radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) {
+               results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
+               if (!results[ret])
+                       continue;
+               if (++ret == max_items)
                        break;
-               cur_index = next_index;
        }
 
        return ret;
@@ -1156,42 +1107,17 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
                unsigned long first_index, unsigned int max_items,
                unsigned int tag)
 {
-       struct radix_tree_node *node;
-       unsigned long max_index;
-       unsigned long cur_index = first_index;
-       unsigned int ret;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned int ret = 0;
 
-       /* check the root's tag bit */
-       if (!root_tag_get(root, tag))
-               return 0;
-
-       node = rcu_dereference_raw(root->rnode);
-       if (!node)
+       if (unlikely(!max_items))
                return 0;
 
-       if (!radix_tree_is_indirect_ptr(node)) {
-               if (first_index > 0)
-                       return 0;
-               results[0] = (void **)&root->rnode;
-               return 1;
-       }
-       node = indirect_to_ptr(node);
-
-       max_index = radix_tree_maxindex(node->height);
-
-       ret = 0;
-       while (ret < max_items) {
-               unsigned int slots_found;
-               unsigned long next_index;       /* Index of next search */
-
-               if (cur_index > max_index)
-                       break;
-               slots_found = __lookup_tag(node, results + ret,
-                               cur_index, max_items - ret, &next_index, tag);
-               ret += slots_found;
-               if (next_index == 0)
+       radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) {
+               results[ret] = slot;
+               if (++ret == max_items)
                        break;
-               cur_index = next_index;
        }
 
        return ret;
index 2654d5c854be244ba1a19509b21d001b5cda15e0..b71012b756f497551b6373c5fc009d25ef7772cf 100644 (file)
@@ -28,8 +28,8 @@
 
 #include <altivec.h>
 #ifdef __KERNEL__
-# include <asm/system.h>
 # include <asm/cputable.h>
+# include <asm/switch_to.h>
 #endif
 
 /*
index c3811bc6b9e33ae88d2575d0387c810b53b95fb8..79c4b2b0b14eec1d05c93e3493dd02e0fd182829 100644 (file)
@@ -813,20 +813,19 @@ EXPORT_SYMBOL(find_or_create_page);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
                            unsigned int nr_pages, struct page **pages)
 {
-       unsigned int i;
-       unsigned int ret;
-       unsigned int nr_found, nr_skip;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned ret = 0;
+
+       if (unlikely(!nr_pages))
+               return 0;
 
        rcu_read_lock();
 restart:
-       nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
-                               (void ***)pages, NULL, start, nr_pages);
-       ret = 0;
-       nr_skip = 0;
-       for (i = 0; i < nr_found; i++) {
+       radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) {
                struct page *page;
 repeat:
-               page = radix_tree_deref_slot((void **)pages[i]);
+               page = radix_tree_deref_slot(slot);
                if (unlikely(!page))
                        continue;
 
@@ -837,7 +836,7 @@ repeat:
                                 * when entry at index 0 moves out of or back
                                 * to root: none yet gotten, safe to restart.
                                 */
-                               WARN_ON(start | i);
+                               WARN_ON(iter.index);
                                goto restart;
                        }
                        /*
@@ -845,7 +844,6 @@ repeat:
                         * here as an exceptional entry: so skip over it -
                         * we only reach this from invalidate_mapping_pages().
                         */
-                       nr_skip++;
                        continue;
                }
 
@@ -853,21 +851,16 @@ repeat:
                        goto repeat;
 
                /* Has the page moved? */
-               if (unlikely(page != *((void **)pages[i]))) {
+               if (unlikely(page != *slot)) {
                        page_cache_release(page);
                        goto repeat;
                }
 
                pages[ret] = page;
-               ret++;
+               if (++ret == nr_pages)
+                       break;
        }
 
-       /*
-        * If all entries were removed before we could secure them,
-        * try again, because callers stop trying once 0 is returned.
-        */
-       if (unlikely(!ret && nr_found > nr_skip))
-               goto restart;
        rcu_read_unlock();
        return ret;
 }
@@ -887,21 +880,22 @@ repeat:
 unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
                               unsigned int nr_pages, struct page **pages)
 {
-       unsigned int i;
-       unsigned int ret;
-       unsigned int nr_found;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned int ret = 0;
+
+       if (unlikely(!nr_pages))
+               return 0;
 
        rcu_read_lock();
 restart:
-       nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
-                               (void ***)pages, NULL, index, nr_pages);
-       ret = 0;
-       for (i = 0; i < nr_found; i++) {
+       radix_tree_for_each_contig(slot, &mapping->page_tree, &iter, index) {
                struct page *page;
 repeat:
-               page = radix_tree_deref_slot((void **)pages[i]);
+               page = radix_tree_deref_slot(slot);
+               /* The hole, there no reason to continue */
                if (unlikely(!page))
-                       continue;
+                       break;
 
                if (radix_tree_exception(page)) {
                        if (radix_tree_deref_retry(page)) {
@@ -924,7 +918,7 @@ repeat:
                        goto repeat;
 
                /* Has the page moved? */
-               if (unlikely(page != *((void **)pages[i]))) {
+               if (unlikely(page != *slot)) {
                        page_cache_release(page);
                        goto repeat;
                }
@@ -934,14 +928,14 @@ repeat:
                 * otherwise we can get both false positives and false
                 * negatives, which is just confusing to the caller.
                 */
-               if (page->mapping == NULL || page->index != index) {
+               if (page->mapping == NULL || page->index != iter.index) {
                        page_cache_release(page);
                        break;
                }
 
                pages[ret] = page;
-               ret++;
-               index++;
+               if (++ret == nr_pages)
+                       break;
        }
        rcu_read_unlock();
        return ret;
@@ -962,19 +956,20 @@ EXPORT_SYMBOL(find_get_pages_contig);
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
                        int tag, unsigned int nr_pages, struct page **pages)
 {
-       unsigned int i;
-       unsigned int ret;
-       unsigned int nr_found;
+       struct radix_tree_iter iter;
+       void **slot;
+       unsigned ret = 0;
+
+       if (unlikely(!nr_pages))
+               return 0;
 
        rcu_read_lock();
 restart:
-       nr_found = radix_tree_gang_lookup_tag_slot(&mapping->page_tree,
-                               (void ***)pages, *index, nr_pages, tag);
-       ret = 0;
-       for (i = 0; i < nr_found; i++) {
+       radix_tree_for_each_tagged(slot, &mapping->page_tree,
+                                  &iter, *index, tag) {
                struct page *page;
 repeat:
-               page = radix_tree_deref_slot((void **)pages[i]);
+               page = radix_tree_deref_slot(slot);
                if (unlikely(!page))
                        continue;
 
@@ -998,21 +993,16 @@ repeat:
                        goto repeat;
 
                /* Has the page moved? */
-               if (unlikely(page != *((void **)pages[i]))) {
+               if (unlikely(page != *slot)) {
                        page_cache_release(page);
                        goto repeat;
                }
 
                pages[ret] = page;
-               ret++;
+               if (++ret == nr_pages)
+                       break;
        }
 
-       /*
-        * If all entries were removed before we could secure them,
-        * try again, because callers stop trying once 0 is returned.
-        */
-       if (unlikely(!ret && nr_found))
-               goto restart;
        rcu_read_unlock();
 
        if (ret)
index b2ee6df0e9bb31eebd3b2f1528cbbcccb2b9c43e..7d698df4a067ce591fd661f45e098610e1a027db 100644 (file)
@@ -5306,6 +5306,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
                return 0;
        }
 
+       if (pmd_trans_unstable(pmd))
+               return 0;
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
        for (; addr != end; pte++, addr += PAGE_SIZE)
                if (get_mctgt_type(vma, addr, *pte, NULL))
@@ -5502,6 +5504,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
                return 0;
        }
 
+       if (pmd_trans_unstable(pmd))
+               return 0;
 retry:
        pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
        for (; addr != end; addr += PAGE_SIZE) {
index caea788628e4dd62060e4838d385e9858f415f25..a712fb9e04ce4c6914c34b4a80f5526c7b49f346 100644 (file)
@@ -1161,11 +1161,47 @@ void drain_local_pages(void *arg)
 }
 
 /*
- * Spill all the per-cpu pages from all CPUs back into the buddy allocator
+ * Spill all the per-cpu pages from all CPUs back into the buddy allocator.
+ *
+ * Note that this code is protected against sending an IPI to an offline
+ * CPU but does not guarantee sending an IPI to newly hotplugged CPUs:
+ * on_each_cpu_mask() blocks hotplug and won't talk to offlined CPUs but
+ * nothing keeps CPUs from showing up after we populated the cpumask and
+ * before the call to on_each_cpu_mask().
  */
 void drain_all_pages(void)
 {
-       on_each_cpu(drain_local_pages, NULL, 1);
+       int cpu;
+       struct per_cpu_pageset *pcp;
+       struct zone *zone;
+
+       /*
+        * Allocate in the BSS so we wont require allocation in
+        * direct reclaim path for CONFIG_CPUMASK_OFFSTACK=y
+        */
+       static cpumask_t cpus_with_pcps;
+
+       /*
+        * We don't care about racing with CPU hotplug event
+        * as offline notification will cause the notified
+        * cpu to drain that CPU pcps and on_each_cpu_mask
+        * disables preemption as part of its processing
+        */
+       for_each_online_cpu(cpu) {
+               bool has_pcps = false;
+               for_each_populated_zone(zone) {
+                       pcp = per_cpu_ptr(zone->pageset, cpu);
+                       if (pcp->pcp.count) {
+                               has_pcps = true;
+                               break;
+                       }
+               }
+               if (has_pcps)
+                       cpumask_set_cpu(cpu, &cpus_with_pcps);
+               else
+                       cpumask_clear_cpu(cpu, &cpus_with_pcps);
+       }
+       on_each_cpu_mask(&cpus_with_pcps, drain_local_pages, NULL, 1);
 }
 
 #ifdef CONFIG_HIBERNATION
@@ -2308,6 +2344,10 @@ rebalance:
                if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) {
                        if (oom_killer_disabled)
                                goto nopage;
+                       /* Coredumps can quickly deplete all memory reserves */
+                       if ((current->flags & PF_DUMPCORE) &&
+                           !(gfp_mask & __GFP_NOFAIL))
+                               goto nopage;
                        page = __alloc_pages_may_oom(gfp_mask, order,
                                        zonelist, high_zoneidx,
                                        nodemask, preferred_zone,
index 29c8716eb7a9a69a4d67501081add66d0d9caa36..e901a36e2520c2b7aa5123ddcd0553415b764397 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1731,6 +1731,52 @@ static int __init cpucache_init(void)
 }
 __initcall(cpucache_init);
 
+static noinline void
+slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
+{
+       struct kmem_list3 *l3;
+       struct slab *slabp;
+       unsigned long flags;
+       int node;
+
+       printk(KERN_WARNING
+               "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n",
+               nodeid, gfpflags);
+       printk(KERN_WARNING "  cache: %s, object size: %d, order: %d\n",
+               cachep->name, cachep->buffer_size, cachep->gfporder);
+
+       for_each_online_node(node) {
+               unsigned long active_objs = 0, num_objs = 0, free_objects = 0;
+               unsigned long active_slabs = 0, num_slabs = 0;
+
+               l3 = cachep->nodelists[node];
+               if (!l3)
+                       continue;
+
+               spin_lock_irqsave(&l3->list_lock, flags);
+               list_for_each_entry(slabp, &l3->slabs_full, list) {
+                       active_objs += cachep->num;
+                       active_slabs++;
+               }
+               list_for_each_entry(slabp, &l3->slabs_partial, list) {
+                       active_objs += slabp->inuse;
+                       active_slabs++;
+               }
+               list_for_each_entry(slabp, &l3->slabs_free, list)
+                       num_slabs++;
+
+               free_objects += l3->free_objects;
+               spin_unlock_irqrestore(&l3->list_lock, flags);
+
+               num_slabs += active_slabs;
+               num_objs = num_slabs * cachep->num;
+               printk(KERN_WARNING
+                       "  node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
+                       node, active_slabs, num_slabs, active_objs, num_objs,
+                       free_objects);
+       }
+}
+
 /*
  * Interface to system's page allocator. No need to hold the cache-lock.
  *
@@ -1757,8 +1803,11 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
                flags |= __GFP_RECLAIMABLE;
 
        page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
-       if (!page)
+       if (!page) {
+               if (!(flags & __GFP_NOWARN) && printk_ratelimit())
+                       slab_out_of_memory(cachep, flags, nodeid);
                return NULL;
+       }
 
        nr_pages = (1 << cachep->gfporder);
        if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
@@ -3696,13 +3745,12 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp,
 
        if (likely(ac->avail < ac->limit)) {
                STATS_INC_FREEHIT(cachep);
-               ac->entry[ac->avail++] = objp;
-               return;
        } else {
                STATS_INC_FREEMISS(cachep);
                cache_flusharray(cachep, ac);
-               ac->entry[ac->avail++] = objp;
        }
+
+       ac->entry[ac->avail++] = objp;
 }
 
 /**
index f4a6229848fdb6bd654c90947f341b6060ab0bde..ffe13fdf8144adadfcc0a55b976f412009e87b38 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -29,6 +29,7 @@
 #include <linux/math64.h>
 #include <linux/fault-inject.h>
 #include <linux/stacktrace.h>
+#include <linux/prefetch.h>
 
 #include <trace/events/kmem.h>
 
@@ -269,6 +270,11 @@ static inline void *get_freepointer(struct kmem_cache *s, void *object)
        return *(void **)(object + s->offset);
 }
 
+static void prefetch_freepointer(const struct kmem_cache *s, void *object)
+{
+       prefetch(object + s->offset);
+}
+
 static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
 {
        void *p;
@@ -1560,6 +1566,7 @@ static void *get_partial_node(struct kmem_cache *s,
                } else {
                        page->freelist = t;
                        available = put_cpu_partial(s, page, 0);
+                       stat(s, CPU_PARTIAL_NODE);
                }
                if (kmem_cache_debug(s) || available > s->cpu_partial / 2)
                        break;
@@ -1983,6 +1990,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                                local_irq_restore(flags);
                                pobjects = 0;
                                pages = 0;
+                               stat(s, CPU_PARTIAL_DRAIN);
                        }
                }
 
@@ -1994,7 +2002,6 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                page->next = oldpage;
 
        } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
-       stat(s, CPU_PARTIAL_FREE);
        return pobjects;
 }
 
@@ -2028,9 +2035,17 @@ static void flush_cpu_slab(void *d)
        __flush_cpu_slab(s, smp_processor_id());
 }
 
+static bool has_cpu_slab(int cpu, void *info)
+{
+       struct kmem_cache *s = info;
+       struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
+
+       return !!(c->page);
+}
+
 static void flush_all(struct kmem_cache *s)
 {
-       on_each_cpu(flush_cpu_slab, s, 1);
+       on_each_cpu_cond(has_cpu_slab, flush_cpu_slab, s, 1, GFP_ATOMIC);
 }
 
 /*
@@ -2319,6 +2334,8 @@ redo:
                object = __slab_alloc(s, gfpflags, node, addr, c);
 
        else {
+               void *next_object = get_freepointer_safe(s, object);
+
                /*
                 * The cmpxchg will only match if there was no additional
                 * operation and if we are on the right processor.
@@ -2334,11 +2351,12 @@ redo:
                if (unlikely(!this_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                object, tid,
-                               get_freepointer_safe(s, object), next_tid(tid)))) {
+                               next_object, next_tid(tid)))) {
 
                        note_cmpxchg_failure("slab_alloc", s, tid);
                        goto redo;
                }
+               prefetch_freepointer(s, next_object);
                stat(s, ALLOC_FASTPATH);
        }
 
@@ -2475,9 +2493,10 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                 * If we just froze the page then put it onto the
                 * per cpu partial list.
                 */
-               if (new.frozen && !was_frozen)
+               if (new.frozen && !was_frozen) {
                        put_cpu_partial(s, page, 1);
-
+                       stat(s, CPU_PARTIAL_FREE);
+               }
                /*
                 * The list lock was not taken therefore no list
                 * activity can be necessary.
@@ -3939,13 +3958,14 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
                if (kmem_cache_open(s, n,
                                size, align, flags, ctor)) {
                        list_add(&s->list, &slab_caches);
+                       up_write(&slub_lock);
                        if (sysfs_slab_add(s)) {
+                               down_write(&slub_lock);
                                list_del(&s->list);
                                kfree(n);
                                kfree(s);
                                goto err;
                        }
-                       up_write(&slub_lock);
                        return s;
                }
                kfree(n);
@@ -5069,6 +5089,8 @@ STAT_ATTR(CMPXCHG_DOUBLE_CPU_FAIL, cmpxchg_double_cpu_fail);
 STAT_ATTR(CMPXCHG_DOUBLE_FAIL, cmpxchg_double_fail);
 STAT_ATTR(CPU_PARTIAL_ALLOC, cpu_partial_alloc);
 STAT_ATTR(CPU_PARTIAL_FREE, cpu_partial_free);
+STAT_ATTR(CPU_PARTIAL_NODE, cpu_partial_node);
+STAT_ATTR(CPU_PARTIAL_DRAIN, cpu_partial_drain);
 #endif
 
 static struct attribute *slab_attrs[] = {
@@ -5134,6 +5156,8 @@ static struct attribute *slab_attrs[] = {
        &cmpxchg_double_cpu_fail_attr.attr,
        &cpu_partial_alloc_attr.attr,
        &cpu_partial_free_attr.attr,
+       &cpu_partial_node_attr.attr,
+       &cpu_partial_drain_attr.attr,
 #endif
 #ifdef CONFIG_FAILSLAB
        &failslab_attr.attr,
index dae42f380d6ebcde88d3aaef6aa3cb1d64e0f5a3..fafc26d1b1dc885d2541eda3bdc5705a4fe56012 100644 (file)
@@ -2022,6 +2022,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        struct page *page = NULL;
        struct inode *inode = NULL;
 
+       if (swap_flags & ~SWAP_FLAGS_VALID)
+               return -EINVAL;
+
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
index 18aded3a89fcc1540e93966a2e5f8be5544b7ffd..61a183b89df6d15c358e7afc2b418411abe5e728 100644 (file)
@@ -626,3 +626,43 @@ int vmtruncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 
        return 0;
 }
+
+/**
+ * truncate_pagecache_range - unmap and remove pagecache that is hole-punched
+ * @inode: inode
+ * @lstart: offset of beginning of hole
+ * @lend: offset of last byte of hole
+ *
+ * This function should typically be called before the filesystem
+ * releases resources associated with the freed range (eg. deallocates
+ * blocks). This way, pagecache will always stay logically coherent
+ * with on-disk format, and the filesystem would not have to deal with
+ * situations such as writepage being called for a page that has already
+ * had its underlying blocks deallocated.
+ */
+void truncate_pagecache_range(struct inode *inode, loff_t lstart, loff_t lend)
+{
+       struct address_space *mapping = inode->i_mapping;
+       loff_t unmap_start = round_up(lstart, PAGE_SIZE);
+       loff_t unmap_end = round_down(1 + lend, PAGE_SIZE) - 1;
+       /*
+        * This rounding is currently just for example: unmap_mapping_range
+        * expands its hole outwards, whereas we want it to contract the hole
+        * inwards.  However, existing callers of truncate_pagecache_range are
+        * doing their own page rounding first; and truncate_inode_pages_range
+        * currently BUGs if lend is not pagealigned-1 (it handles partial
+        * page at start of hole, but not partial page at end of hole).  Note
+        * unmap_mapping_range allows holelen 0 for all, and we allow lend -1.
+        */
+
+       /*
+        * Unlike in truncate_pagecache, unmap_mapping_range is called only
+        * once (before truncating pagecache), and without "even_cows" flag:
+        * hole-punching should not remove private COWed pages from the hole.
+        */
+       if ((u64)unmap_end > (u64)unmap_start)
+               unmap_mapping_range(mapping, unmap_start,
+                                   1 + unmap_end - unmap_start, 0);
+       truncate_inode_pages_range(mapping, lstart, lend);
+}
+EXPORT_SYMBOL(truncate_pagecache_range);
index bd345f3d29f855f9792c4ebdf69c2aabee2d0021..b324e31401a9e04cf3fe8fda8b1de009400e7e71 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 94b3ad08f39a12ce92d5ccd9d65ade1d01157470..5ab25cd4314b6f18292c2c34603de70cb955d435 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <linux/module.h>
-#include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 91aca8780fd05bea28a084dced4821cfb48caf3b..056794e6637536c043f1de97a331d090e5f9c7a6 100644 (file)
@@ -35,7 +35,6 @@
 #include <net/arp.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 /*
  * Create the HIPPI MAC header for an arbitrary protocol layer
index 5e20cf8a074bb56429320118b460b06dba8b0466..b9a3a145e34809f291dc2b4d8e94d0d993bcbfcd 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 5de42ea309bc9e1d9c4dbdb583b04fa5814651ba..8ae3a7879335f28cc082ea6c2a3bf8da2b8820a3 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/param.h> /* for HZ */
 #include <linux/uaccess.h>
 #include <asm/byteorder.h> /* for htons etc. */
-#include <asm/system.h> /* save/restore_flags */
 #include <linux/atomic.h>
 
 #include "common.h"
index 3cd0a0dc91cb6b3823271ccd109ab021dc5abef1..0906c194a4139b1cf56e368876c7ba463e911c5b 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 7e7964dd987bc99a311084c285ea27e225082b57..9162409559cf3b3845f6eb27c36f7d81b9409851 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c1cb982f6e86954018c7311d17016cb2189f9bf1..d0de30e89591c9bd9881286d96698ed61656723c 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 8273b1200eeefe701974106ed3ddbc39ed973621..9bd31e88aeca9b71aa9dda70105b7df9391bb988 100644 (file)
@@ -23,7 +23,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 85816e612dc0a83cd76b56a5d81448d90cd28b20..5ea7fd3e2af9300774598bc3a10afdbdc38a969b 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c7d81436213d13e24e67edf2630930e5c4ed08c0..993c439b4f71f0c8dcf1db8e7d62ff2325c488f2 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 60b545e2822acee4e3a30a0cfd53ccb564dadd53..7d5f24b82cc878672bf9a885258f0c9c09791906 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 9bb7765412036dc19001ea412c346e12990148c3..96f4cab3a2f96c09176e3cb686657c0d9892d0aa 100644 (file)
@@ -27,7 +27,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index cf0c47a265304bc94cc391c7c92a10be16de14ed..846ae4e2b115ea484a86f811dad504ed0099329f 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 37507d806f65f64d6b1740dc055fea80845ff644..be8a25e0db650db000d8ded25e27fa6e8186e3a0 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/netfilter.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 87fddab22e0f3b9d1961ae53461cb7f1dc49d8ac..a65588040b9e980ed89f6c33d28fc6dd5af450be 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/spinlock.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index a8eef88d86529d510e857e568c34be681d80bcfd..3fbf8f7b2cf46a394b5d5321a38880d3b6df4bc4 100644 (file)
@@ -30,7 +30,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 277f81bb979a6f0dc0d19b754a0f7e356753f7c7..8b66a41e538f272213092b5fe0faf7d404db9854 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 96e4b9273250918b4a60fdcc9ccce00b79090827..004467c9e6e15ada9c6eae056cabff7dd8d5777e 100644 (file)
@@ -25,7 +25,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c6715ee4ab8f6099e25a58421998127df1a96dda..1997538a5d23d93ddca9724fd3787dc0b0b2595a 100644 (file)
@@ -26,7 +26,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index db29ea71e80a599cd667a8d7d0730531f0a90ea3..c3cffa79bafb92aefdba18a63b59fa3b29b30a86 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 4c83137b59546ce01a767538a8d249796651c4ab..e3c579ba632527ed14debcb0b0b274dbd365074a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 9f9c8dcd8af01bbae591733a093344126f0b9500..180bfc45810da0217e4639dbd6d154a91a63c128 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/uaccess.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 
 #include "bnep.h"
 
index 1230faaac29b01c54abac33a4913851db085ab22..311668d14571626dac778201a65ed21f05c72cbe 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <linux/isdn/capilli.h>
 
-#include <asm/system.h>
 
 #include "cmtp.h"
 
index 947172bf16219e7d1df1f0efcf9c3c70018c7870..5238b6b3ea6abbd7b67026825506ef190b64fdda 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/interrupt.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 59ec99eb739b2d403ce2a25630d50d195c9b1263..e33af63a884a476e689af34a3a56003d2f485f2f 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/crypto.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index badb7851d11669a8da55be315bc77054c5eaf7a3..b37531094c4999a6b9224056e4d5f283a9bdcece 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/interrupt.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 63afd234283e1af474dedffc0843caad1ad8d627..5914623f426aa835aadee48c6ec8eb8400ab7728 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/ioctl.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
@@ -734,7 +733,8 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
                data = &tv;
                len = sizeof(tv);
 #ifdef CONFIG_COMPAT
-               if (msg->msg_flags & MSG_CMSG_COMPAT) {
+               if (!COMPAT_USE_64BIT_TIME &&
+                   (msg->msg_flags & MSG_CMSG_COMPAT)) {
                        ctv.tv_sec = tv.tv_sec;
                        ctv.tv_usec = tv.tv_usec;
                        data = &ctv;
index 3e450f4a3125338c8d38b68d1441d545ec9ad2e3..b8e17e4dac8b4179d9ac82ad916baf28ed333662 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/crc16.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
index 22169c3f148254c52b991caf64b7c0284a54d7f6..a55a43e9f70e9d35181f1272c3897ac43856a6d9 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/security.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include <net/bluetooth/bluetooth.h>
index 8bf26d1bc5c181e25641622d980c0f812a6780e0..f6ab12907963fac3d5e3ed6bae46d10b28ee52db 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/security.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include <net/bluetooth/bluetooth.h>
index 64b4515a64e6e7e6002b0f923b8ef3902406854f..e055708b8ec9dfaa894e8e5920b4c35fd38b2afe 100644 (file)
@@ -219,8 +219,6 @@ Efault:
 
 int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
 {
-       struct compat_timeval ctv;
-       struct compat_timespec cts[3];
        struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
        struct compat_cmsghdr cmhdr;
        int cmlen;
@@ -230,24 +228,28 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
                return 0; /* XXX: return error? check spec. */
        }
 
-       if (level == SOL_SOCKET && type == SCM_TIMESTAMP) {
-               struct timeval *tv = (struct timeval *)data;
-               ctv.tv_sec = tv->tv_sec;
-               ctv.tv_usec = tv->tv_usec;
-               data = &ctv;
-               len = sizeof(ctv);
-       }
-       if (level == SOL_SOCKET &&
-           (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) {
-               int count = type == SCM_TIMESTAMPNS ? 1 : 3;
-               int i;
-               struct timespec *ts = (struct timespec *)data;
-               for (i = 0; i < count; i++) {
-                       cts[i].tv_sec = ts[i].tv_sec;
-                       cts[i].tv_nsec = ts[i].tv_nsec;
+       if (!COMPAT_USE_64BIT_TIME) {
+               struct compat_timeval ctv;
+               struct compat_timespec cts[3];
+               if (level == SOL_SOCKET && type == SCM_TIMESTAMP) {
+                       struct timeval *tv = (struct timeval *)data;
+                       ctv.tv_sec = tv->tv_sec;
+                       ctv.tv_usec = tv->tv_usec;
+                       data = &ctv;
+                       len = sizeof(ctv);
+               }
+               if (level == SOL_SOCKET &&
+                   (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) {
+                       int count = type == SCM_TIMESTAMPNS ? 1 : 3;
+                       int i;
+                       struct timespec *ts = (struct timespec *)data;
+                       for (i = 0; i < count; i++) {
+                               cts[i].tv_sec = ts[i].tv_sec;
+                               cts[i].tv_nsec = ts[i].tv_nsec;
+                       }
+                       data = &cts;
+                       len = sizeof(cts[0]) * count;
                }
-               data = &cts;
-               len = sizeof(cts[0]) * count;
        }
 
        cmlen = CMSG_COMPAT_LEN(len);
@@ -454,11 +456,15 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
 
 int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
 {
-       struct compat_timeval __user *ctv =
-                       (struct compat_timeval __user *) userstamp;
-       int err = -ENOENT;
+       struct compat_timeval __user *ctv;
+       int err;
        struct timeval tv;
 
+       if (COMPAT_USE_64BIT_TIME)
+               return sock_get_timestamp(sk, userstamp);
+
+       ctv = (struct compat_timeval __user *) userstamp;
+       err = -ENOENT;
        if (!sock_flag(sk, SOCK_TIMESTAMP))
                sock_enable_timestamp(sk, SOCK_TIMESTAMP);
        tv = ktime_to_timeval(sk->sk_stamp);
@@ -478,11 +484,15 @@ EXPORT_SYMBOL(compat_sock_get_timestamp);
 
 int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
 {
-       struct compat_timespec __user *ctv =
-                       (struct compat_timespec __user *) userstamp;
-       int err = -ENOENT;
+       struct compat_timespec __user *ctv;
+       int err;
        struct timespec ts;
 
+       if (COMPAT_USE_64BIT_TIME)
+               return sock_get_timestampns (sk, userstamp);
+
+       ctv = (struct compat_timespec __user *) userstamp;
+       err = -ENOENT;
        if (!sock_flag(sk, SOCK_TIMESTAMP))
                sock_enable_timestamp(sk, SOCK_TIMESTAMP);
        ts = ktime_to_timespec(sk->sk_stamp);
@@ -767,6 +777,11 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
        int datagrams;
        struct timespec ktspec;
 
+       if (COMPAT_USE_64BIT_TIME)
+               return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
+                                     flags | MSG_CMSG_COMPAT,
+                                     (struct timespec *) timeout);
+
        if (timeout == NULL)
                return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
                                      flags | MSG_CMSG_COMPAT, NULL);
index d3cf12f62c8f213fc2c2a33797c1749f1d18be88..e4fbfd6e2bd43a0cda49f705058631a1bfec7811 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
index 452db7090d18b39995a302843d05eeed0042414d..5d59155adf2a27a8f54b7cbe09210dedf22efb6e 100644 (file)
@@ -73,7 +73,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/cpu.h>
index 5dea452792155fffa062a59641c1862e26f19fe0..cf4989ac503bcc8163f90ee0e3e9610155845551 100644 (file)
@@ -33,7 +33,6 @@
 #include <net/sock.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/filter.h>
index 43b03dd71e85da9b6d2043beb531cd4289d0531a..d9d198aa9fed0738288973815b427ec6bae0de4a 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
index 1a63c6efd2eaed0bad1582bd0c1a07a83ed73fb6..90430b776ecef76ecb71b1ed4db964b541a382fc 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/pci.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/inet.h>
 #include <linux/netdevice.h>
index ff52ad0a51501c98891401d6e29f18dfab80ade9..611c5efd4cb0b71abeb9b3d965acbf490673e644 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include <net/protocol.h>
index a690cae91cdd14641b61844f6ac1f903fbf9666e..f223cdc75da6af27a688430ee98c0743608ea822 100644 (file)
@@ -66,7 +66,6 @@
 #include <net/xfrm.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <trace/events/skb.h>
 
 #include "kmap_skb.h"
index 9be6d0d6c5335e0f14ad61a26c1837e5b693e648..b2e14c07d9205467f0a8d83af3fe6108d277a15f 100644 (file)
 #include <linux/memcontrol.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/netdevice.h>
 #include <net/protocol.h>
index 386e263f60669a3a25be7e6d8a4361d7ce93161e..dc3c3faff2f4a70e878953dc8ba910308182b728 100644 (file)
@@ -30,7 +30,6 @@
 #include <net/net_ratelimit.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 int net_msg_warn __read_mostly = 1;
index 19acd00a63826b66bb3f8076bc75b7fa48d2f241..4136987d94da299abb50bef85e5e360560439710 100644 (file)
@@ -119,7 +119,6 @@ Version 0.0.6    2.1.110   07-aug-98   Eduardo Marcelo Serrat
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <net/flow.h>
-#include <asm/system.h>
 #include <asm/ioctls.h>
 #include <linux/capability.h>
 #include <linux/mm.h>
index 74d321a60e7b5751901c2a2e7d185e54043185ec..c00e3077988c07005a9633f859c1b76a54018ca8 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/notifier.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <net/net_namespace.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
index 73fa268fe2e8b40d977ec258a3d6b47ebf644c2c..f6544b2c91b006ad2b78090fba29b2b65d43da4d 100644 (file)
@@ -60,7 +60,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
index bd78836a81eb3fe1965d5abdd4fcff62e11b9f4b..e446e85e64a61797be68cc8cf7dd8549ab0712d6 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/route.h>
 #include <linux/slab.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
index 7e717cb35ad15c7437dba106107cf4cebb653a52..71b5edcee4016948f2075decbdc692d345dfc192 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/mutex.h>
 
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 static const struct proto_ops econet_ops;
 static struct hlist_head econet_sklist;
index a93af86b84741c96aca902e75402c7b381de47b0..bf10a311cf1c837a5fd96d936b51a9f798852d0c 100644 (file)
@@ -59,7 +59,6 @@
 #include <net/ip.h>
 #include <net/dsa.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 __setup("ether=", netdev_boot_setup);
 
index fdf49fd44bb40a30aa4af31171a190dc8ed6256e..10e3751466b502edd4a4bee3fe91affc5c470f11 100644 (file)
@@ -91,7 +91,6 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/inet.h>
 #include <linux/igmp.h>
index 73f46d691abcc71cb382cfd951427e15ff9573b1..18d9b81ecb1ac2a61d53b492a81781ad0bcfc2d8 100644 (file)
 #include <net/ax25.h>
 #include <net/netrom.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include <linux/netfilter_arp.h>
index d4fad5c774471529dbe76703a7c4e95d2b694b6e..6e447ff94dfa5881876ca1a1a86f5f0f1df3b9ae 100644 (file)
@@ -27,7 +27,6 @@
 
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/module.h>
index 76e72bacc217a5c3ad30ca0dcac209fec41b7c29..cbe3a68507cf89809cfc94dd1770afef1f223ac5 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/types.h>
index a8c5c1d6715b10f392419f1a256075dfb97ff38b..5063fa38ac7becd71bf0eea737e596f9567b48a5 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index da9b9cb2282de5e060e09542afb2dd51957772a7..bce36f1a37b43b5cdbc811ead5b1a01f52de82da 100644 (file)
@@ -51,7 +51,6 @@
 #define VERSION "0.409"
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 9664d353ccd8af79c4e0dedf9933c61d2e92835d..2cb2bf845641da6bee915edfb73240c9e675c565 100644 (file)
@@ -91,7 +91,6 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
index 450e5d21ed2af271574874479bd0c0d341bf6b38..5dfecfd7d5e9fb9cfe154ad21eb93de60a3fd152 100644 (file)
@@ -73,7 +73,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
index f3f1108940f5ee719bafde02bf9f672cc3b49f2f..26eccc5bab1c28e81d170fa0c147c9fb33a499e8 100644 (file)
 
 #define pr_fmt(fmt) "IPv4: " fmt
 
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index ff302bde8890fb748b026e07d55b3ace325335d7..4910176d24ed5d8b4a8a5430a3bc3e33d8c1ba91 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 0518a4fb177bbc8c424c930351ddba636d42198f..960fbfc3e976f5c8c65a2a95c8d3bd5946c0ec33 100644 (file)
@@ -26,7 +26,6 @@
  *
  */
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/capability.h>
index ab6b36e6da153638714c8a716e23a9832b432f49..50009c787bcdc3ae79291adf6e688dad2d612331 100644 (file)
@@ -20,7 +20,6 @@
  *
  */
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
index 12ccf880eb88377161eb1eae3f5e66ceb41de8b4..4dc1c104c942204882acadcf73e709683ebaafd6 100644 (file)
@@ -66,7 +66,6 @@
 
 #include <linux/module.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index d6f5feeb3eaf9e780f25acbdd360467beddc2536..fe141052a1beaf5c85376cfed0740c348c019dce 100644 (file)
@@ -79,7 +79,6 @@
 
 #define pr_fmt(fmt) "UDP: " fmt
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <linux/bootmem.h>
index 5605f9dca87e45cdd6b21dcc02864d2f5648160f..8ed1b930e75f09adb02d62897e2bf0b0c8163bde 100644 (file)
@@ -60,7 +60,6 @@
 #endif
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/mroute6.h>
 
 MODULE_AUTHOR("Cast of dozens");
index af88934e4d79aebe751d420737866656418397af..27ac95a6342927e5365af6616af82815e603619e 100644 (file)
@@ -66,7 +66,6 @@
 #include <net/inet_common.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 /*
  *     The ICMP socket(s). This is the most convenient way to flow control
index 5aa3981a392273891881ea8defc1d70fff7adde4..8110362e0af558a9ff77824bc78c1b3677369855 100644 (file)
@@ -16,7 +16,6 @@
  *
  */
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
index ba1a3fc39b5c599ef9578683b66f3c229d7de1f0..42cf1390ce9c89736e18e6a6b61c14227c4c3e7b 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/bitops.h>
 #include <net/arp.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
index 579617cca125e014cd93506e5d419c8c94f8aff1..7ac4d1becbfca373330c8618b4f865c304433e95 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/moduleparam.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
index 8b61cf0d8a69817cc70c5dfdb71c921efb9f3a90..32dcaac70b0caa9a10dc09a1ed4e90efaf5891ed 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
index f418cb2ad49ccdf00557e673147f93d748c74409..1d552b3946fc2aef6d069194347505c876b4c633 100644 (file)
@@ -24,7 +24,6 @@
  *
  ********************************************************************/
 
-#include <asm/system.h>
 #include <linux/delay.h>
 
 #include <net/irda/timer.h>
index 8d0324bac01ca8c49858e5c44a20f28c7a2a36c5..ab3d35f23257e12809a8c36809d8798d68a97662 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 2ec1af5c36cc1479e229568001b77b3f6cf7f106..f4e3c1accab7007e0dd7d544f9493e0ebeec3d55 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c75a79540f9f476b2247a4c96d6004625f528201..baab2760f651a060abf63de590b5e8ca7c888cb0 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 43a2a7fb327b3888dd726dc3325408c24255a16a..066225b4e82448a24dc0103c0163bc113a75b219 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index af6d14b44e2e66abe826896c8fb4c2672f661509..f8cd641dfc8293195ca5d572ad987de9b846dd3a 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index fe6cb4304d72fbdf461f63f4eaad9bf0cda6e35e..52856178c9d775eaa1b77cb35f0be75ee3e2fc86 100644 (file)
@@ -31,7 +31,6 @@
 #include <net/net_namespace.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
-#include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
index 85312939695f86f59357039799cb14364e1f638e..f843a88332509edc9ac7ed509cba6d679685664f 100644 (file)
@@ -25,7 +25,6 @@
 #include <net/protocol.h>
 #include <net/tcp.h>
 #include <net/udp.h>
-#include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
index 4d70785b953daad4c1bc7459652427a3ef86e685..e6ddde165612d11e77e4c2e66086088eb5fead57 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <linux/init.h>
index 7dab229bfbcca3c67aa6112ec4a19a40c411adcb..06592d8b4a2b4eba33d9e71e44fc75ca206b38a8 100644 (file)
@@ -31,7 +31,6 @@
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 64e6dde9749d5e713d15ac23914e3928211aa395..1c51d7a58f0b0c75a61c9d8b20f71d15485e18bc 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/if_ether.h>    /* For the statistics structure. */
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
index 6d4ef6d65b3df789d3eb4b3449df1fd1f2a5ced3..c3073a2ef6342f32528cbc04cec65c08789749ee 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 607fddb4fdbbd944b1dad88400061455f03909a4..0b4bcb2bf38f3c49f05aa609122a54c7ef6ff21b 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 2cf330162d7e8e21ddcbc21eb741336e332ec422..70ffff76a967e0f439796ec9ffde93a67cd8454e 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 6a947ae50dbdd9865e2607041a4b12f2a7e13fcc..ca40e2298f5a583f569d018c4da69c725dec014e 100644 (file)
@@ -23,7 +23,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 1cb98e88f5e1cef557699464d6d9519ac14c9a85..ff2c1b142f578ea60d9d3e16fa466bc20c62fec9 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 2c030505b335fd3ef9ab971fb9abd664548d8c38..e44e631ea952d3aadd1770f1e85b69b38b004325 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/udp.h>
 #include <linux/ethtool.h>
 #include <linux/wait.h>
-#include <asm/system.h>
 #include <asm/div64.h>
 #include <linux/highmem.h>
 #include <linux/netfilter_bridge.h>
index ae2d484416dd5170b3c4eed8bd820ee594e5e474..4f2c0df795639a97d1d2c0b7cfabe1779e6f103d 100644 (file)
@@ -73,7 +73,6 @@
 #include <net/sock.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <asm/page.h>
index f9ea925ad9cb6c1628bf6f38a57c4f49c210b589..c4719ce604c28040b1cfdc9bff0f3a9ee4d2200d 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>
index 178ff4f73c85102518025fa3d4e20f647a389743..1ab8689726ec994644b4342772007a26cbcbba01 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/if_ether.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <linux/inet.h>
index 7f7fcb46b4fa00371201dee0e83f17819db9c5e3..79c4abcfa6b4ee86fbd92358f5585f88b74319f5 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 7a02bd1cc5a0b838c43a9668c0e52b8685040ea6..bc5514211b0cfb4b3d4d42a12eeb03de8e90a2b4 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 4ebf33afbe473c31098ab6e80674ef3d6198892e..9ad98b524646c935b9728baddb7b8cdf00cffd00 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index cd9b7ee60f3e6937a3c6193423c4a274f171136b..40148932c8a4bd0eb8dca481f73f7f5721090340 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
index f6c71caa94b9d8b7fe2d7873264929218af2a97c..47f1fdb346b01b3e15461b71a64a5f953fdaec7f 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index b6c8f38cc26c42025ea9b6c63558f2d032c1f92d..bc5469d6d9cb5cdf6e7995e3ee605f97d2dd2616 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 12a48d846223c5d2204e753fe9ae6298d55ff489..484cc6953fc61ebcb049604e5dbdb57a4ffcd385 100644 (file)
@@ -2592,7 +2592,7 @@ void socket_seq_show(struct seq_file *seq)
 
 #ifdef CONFIG_COMPAT
 static int do_siocgstamp(struct net *net, struct socket *sock,
-                        unsigned int cmd, struct compat_timeval __user *up)
+                        unsigned int cmd, void __user *up)
 {
        mm_segment_t old_fs = get_fs();
        struct timeval ktv;
@@ -2601,15 +2601,14 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        set_fs(KERNEL_DS);
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
-       if (!err) {
-               err = put_user(ktv.tv_sec, &up->tv_sec);
-               err |= __put_user(ktv.tv_usec, &up->tv_usec);
-       }
+       if (!err)
+               err = compat_put_timeval(up, &ktv);
+
        return err;
 }
 
 static int do_siocgstampns(struct net *net, struct socket *sock,
-                        unsigned int cmd, struct compat_timespec __user *up)
+                          unsigned int cmd, void __user *up)
 {
        mm_segment_t old_fs = get_fs();
        struct timespec kts;
@@ -2618,10 +2617,9 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        set_fs(KERNEL_DS);
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
-       if (!err) {
-               err = put_user(kts.tv_sec, &up->tv_sec);
-               err |= __put_user(kts.tv_nsec, &up->tv_nsec);
-       }
+       if (!err)
+               err = compat_put_timespec(up, &kts);
+
        return err;
 }
 
index f21ece08876440d574dad1ac6a09cf22d40d043e..de0b0f39d9d85430f8c7f3af17884473b133120e 100644 (file)
@@ -830,6 +830,8 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf,
 {
        ssize_t ret;
 
+       if (count == 0)
+               return -EINVAL;
        if (copy_from_user(kaddr, buf, count))
                return -EFAULT;
        kaddr[count] = '\0';
index 7a4cb5fdc21239d3628f44c912018399121b14e5..67972462a543d1bad6326ec214c73bc9dce17d0b 100644 (file)
@@ -17,7 +17,6 @@
  *  Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <asm/system.h>
 
 #include <linux/module.h>
 #include <linux/types.h>
index c84c0e0c41cb39dd41d37c3cc23c875b98c1e4d7..0af37fc468181e9a6917c695d8f60dd381734e78 100644 (file)
@@ -1014,6 +1014,7 @@ enum {
        RPCAUTH_statd,
        RPCAUTH_nfsd4_cb,
        RPCAUTH_cache,
+       RPCAUTH_nfsd,
        RPCAUTH_RootEOF
 };
 
@@ -1046,6 +1047,10 @@ static const struct rpc_filelist files[] = {
                .name = "cache",
                .mode = S_IFDIR | S_IRUGO | S_IXUGO,
        },
+       [RPCAUTH_nfsd] = {
+               .name = "nfsd",
+               .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+       },
 };
 
 /*
index 207a74696c9f84a62df704c94190ed28474c23b0..78ac39fd9fe7556a71dc361406904cf8bb32d7b2 100644 (file)
@@ -734,7 +734,7 @@ void rpcb_getport_async(struct rpc_task *task)
        map->r_vers = clnt->cl_vers;
        map->r_prot = xprt->prot;
        map->r_port = 0;
-       map->r_xprt = xprt_get(xprt);
+       map->r_xprt = xprt;
        map->r_status = -EIO;
 
        switch (bind_version) {
index bcd574f2ac566a96c34b041f44ce1e0b1bedbed8..521d8f7dc833ac769afe83daf0b03fe818c5be32 100644 (file)
@@ -507,7 +507,7 @@ static int unix_gid_parse(struct cache_detail *cd,
        time_t expiry;
        struct unix_gid ug, *ugp;
 
-       if (mlen <= 0 || mesg[mlen-1] != '\n')
+       if (mesg[mlen - 1] != '\n')
                return -EINVAL;
        mesg[mlen-1] = 0;
 
index 40ae884db865f975f589a433432652d0fe1936ed..824d32fb31214b5f433f439c439e7161fba28fb5 100644 (file)
@@ -1381,8 +1381,6 @@ void svc_sock_update_bufs(struct svc_serv *serv)
        spin_lock_bh(&serv->sv_lock);
        list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list)
                set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
-       list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list)
-               set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
        spin_unlock_bh(&serv->sv_lock);
 }
 EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
index 09af4fab1a456c32c5c7b414ab8923cb29a8ef02..8343737e85f4d87136fd4adff6c0d4ba296e0c2c 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/svc_rdma.h>
+#include "xprt_rdma.h"
 
 #define RPCDBG_FACILITY        RPCDBG_SVCXPRT
 
index 9530ef2d40dc73c6c0849f761f399aff38121466..8d2edddf48cf13c6d283bd8784e61c7601f23fc7 100644 (file)
@@ -60,21 +60,11 @@ static u32 *decode_read_list(u32 *va, u32 *vaend)
        struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va;
 
        while (ch->rc_discrim != xdr_zero) {
-               u64 ch_offset;
-
                if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) >
                    (unsigned long)vaend) {
                        dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch);
                        return NULL;
                }
-
-               ch->rc_discrim = ntohl(ch->rc_discrim);
-               ch->rc_position = ntohl(ch->rc_position);
-               ch->rc_target.rs_handle = ntohl(ch->rc_target.rs_handle);
-               ch->rc_target.rs_length = ntohl(ch->rc_target.rs_length);
-               va = (u32 *)&ch->rc_target.rs_offset;
-               xdr_decode_hyper(va, &ch_offset);
-               put_unaligned(ch_offset, (u64 *)va);
                ch++;
        }
        return (u32 *)&ch->rc_position;
@@ -91,7 +81,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
        *byte_count = 0;
        *ch_count = 0;
        for (; ch->rc_discrim != 0; ch++) {
-               *byte_count = *byte_count + ch->rc_target.rs_length;
+               *byte_count = *byte_count + ntohl(ch->rc_target.rs_length);
                *ch_count = *ch_count + 1;
        }
 }
@@ -108,7 +98,8 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
  */
 static u32 *decode_write_list(u32 *va, u32 *vaend)
 {
-       int ch_no;
+       int nchunks;
+
        struct rpcrdma_write_array *ary =
                (struct rpcrdma_write_array *)va;
 
@@ -121,37 +112,24 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
                dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend);
                return NULL;
        }
-       ary->wc_discrim = ntohl(ary->wc_discrim);
-       ary->wc_nchunks = ntohl(ary->wc_nchunks);
+       nchunks = ntohl(ary->wc_nchunks);
        if (((unsigned long)&ary->wc_array[0] +
-            (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) >
+            (sizeof(struct rpcrdma_write_chunk) * nchunks)) >
            (unsigned long)vaend) {
                dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
-                       ary, ary->wc_nchunks, vaend);
+                       ary, nchunks, vaend);
                return NULL;
        }
-       for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) {
-               u64 ch_offset;
-
-               ary->wc_array[ch_no].wc_target.rs_handle =
-                       ntohl(ary->wc_array[ch_no].wc_target.rs_handle);
-               ary->wc_array[ch_no].wc_target.rs_length =
-                       ntohl(ary->wc_array[ch_no].wc_target.rs_length);
-               va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset;
-               xdr_decode_hyper(va, &ch_offset);
-               put_unaligned(ch_offset, (u64 *)va);
-       }
-
        /*
         * rs_length is the 2nd 4B field in wc_target and taking its
         * address skips the list terminator
         */
-       return (u32 *)&ary->wc_array[ch_no].wc_target.rs_length;
+       return (u32 *)&ary->wc_array[nchunks].wc_target.rs_length;
 }
 
 static u32 *decode_reply_array(u32 *va, u32 *vaend)
 {
-       int ch_no;
+       int nchunks;
        struct rpcrdma_write_array *ary =
                (struct rpcrdma_write_array *)va;
 
@@ -164,28 +142,15 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend)
                dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend);
                return NULL;
        }
-       ary->wc_discrim = ntohl(ary->wc_discrim);
-       ary->wc_nchunks = ntohl(ary->wc_nchunks);
+       nchunks = ntohl(ary->wc_nchunks);
        if (((unsigned long)&ary->wc_array[0] +
-            (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) >
+            (sizeof(struct rpcrdma_write_chunk) * nchunks)) >
            (unsigned long)vaend) {
                dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
-                       ary, ary->wc_nchunks, vaend);
+                       ary, nchunks, vaend);
                return NULL;
        }
-       for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) {
-               u64 ch_offset;
-
-               ary->wc_array[ch_no].wc_target.rs_handle =
-                       ntohl(ary->wc_array[ch_no].wc_target.rs_handle);
-               ary->wc_array[ch_no].wc_target.rs_length =
-                       ntohl(ary->wc_array[ch_no].wc_target.rs_length);
-               va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset;
-               xdr_decode_hyper(va, &ch_offset);
-               put_unaligned(ch_offset, (u64 *)va);
-       }
-
-       return (u32 *)&ary->wc_array[ch_no];
+       return (u32 *)&ary->wc_array[nchunks];
 }
 
 int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req,
@@ -386,13 +351,14 @@ void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *ary,
 
 void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary,
                                     int chunk_no,
-                                    u32 rs_handle, u64 rs_offset,
+                                    __be32 rs_handle,
+                                    __be64 rs_offset,
                                     u32 write_len)
 {
        struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target;
-       seg->rs_handle = htonl(rs_handle);
+       seg->rs_handle = rs_handle;
+       seg->rs_offset = rs_offset;
        seg->rs_length = htonl(write_len);
-       xdr_encode_hyper((u32 *) &seg->rs_offset, rs_offset);
 }
 
 void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt,
index df67211c4bafa34449d7449cf221e354884bd39d..41cb63b623dfa5033388740d454f937c84ae1db3 100644 (file)
@@ -147,7 +147,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt,
        page_off = 0;
        ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
        ch_no = 0;
-       ch_bytes = ch->rc_target.rs_length;
+       ch_bytes = ntohl(ch->rc_target.rs_length);
        head->arg.head[0] = rqstp->rq_arg.head[0];
        head->arg.tail[0] = rqstp->rq_arg.tail[0];
        head->arg.pages = &head->pages[head->count];
@@ -183,7 +183,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt,
                        ch_no++;
                        ch++;
                        chl_map->ch[ch_no].start = sge_no;
-                       ch_bytes = ch->rc_target.rs_length;
+                       ch_bytes = ntohl(ch->rc_target.rs_length);
                        /* If bytes remaining account for next chunk */
                        if (byte_count) {
                                head->arg.page_len += ch_bytes;
@@ -281,11 +281,12 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt,
        offset = 0;
        ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
        for (ch_no = 0; ch_no < ch_count; ch_no++) {
+               int len = ntohl(ch->rc_target.rs_length);
                rpl_map->sge[ch_no].iov_base = frmr->kva + offset;
-               rpl_map->sge[ch_no].iov_len = ch->rc_target.rs_length;
+               rpl_map->sge[ch_no].iov_len = len;
                chl_map->ch[ch_no].count = 1;
                chl_map->ch[ch_no].start = ch_no;
-               offset += ch->rc_target.rs_length;
+               offset += len;
                ch++;
        }
 
@@ -316,7 +317,7 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt,
        for (i = 0; i < count; i++) {
                ctxt->sge[i].length = 0; /* in case map fails */
                if (!frmr) {
-                       BUG_ON(0 == virt_to_page(vec[i].iov_base));
+                       BUG_ON(!virt_to_page(vec[i].iov_base));
                        off = (unsigned long)vec[i].iov_base & ~PAGE_MASK;
                        ctxt->sge[i].addr =
                                ib_dma_map_page(xprt->sc_cm_id->device,
@@ -426,6 +427,7 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt,
 
        for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
             ch->rc_discrim != 0; ch++, ch_no++) {
+               u64 rs_offset;
 next_sge:
                ctxt = svc_rdma_get_context(xprt);
                ctxt->direction = DMA_FROM_DEVICE;
@@ -440,10 +442,10 @@ next_sge:
                read_wr.opcode = IB_WR_RDMA_READ;
                ctxt->wr_op = read_wr.opcode;
                read_wr.send_flags = IB_SEND_SIGNALED;
-               read_wr.wr.rdma.rkey = ch->rc_target.rs_handle;
-               read_wr.wr.rdma.remote_addr =
-                       get_unaligned(&(ch->rc_target.rs_offset)) +
-                       sgl_offset;
+               read_wr.wr.rdma.rkey = ntohl(ch->rc_target.rs_handle);
+               xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset,
+                                &rs_offset);
+               read_wr.wr.rdma.remote_addr = rs_offset + sgl_offset;
                read_wr.sg_list = ctxt->sge;
                read_wr.num_sge =
                        rdma_read_max_sge(xprt, chl_map->ch[ch_no].count);
index 249a835b703f1f0ec46c6051ff98249227876509..42eb7ba0b9034afc1ade6770fea5d49fe305cc97 100644 (file)
@@ -409,21 +409,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
                u64 rs_offset;
 
                arg_ch = &arg_ary->wc_array[chunk_no].wc_target;
-               write_len = min(xfer_len, arg_ch->rs_length);
+               write_len = min(xfer_len, ntohl(arg_ch->rs_length));
 
                /* Prepare the response chunk given the length actually
                 * written */
-               rs_offset = get_unaligned(&(arg_ch->rs_offset));
+               xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset);
                svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
-                                           arg_ch->rs_handle,
-                                           rs_offset,
-                                           write_len);
+                                               arg_ch->rs_handle,
+                                               arg_ch->rs_offset,
+                                               write_len);
                chunk_off = 0;
                while (write_len) {
                        int this_write;
                        this_write = min(write_len, max_write);
                        ret = send_write(xprt, rqstp,
-                                        arg_ch->rs_handle,
+                                        ntohl(arg_ch->rs_handle),
                                         rs_offset + chunk_off,
                                         xdr_off,
                                         this_write,
@@ -457,6 +457,7 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
        u32 xdr_off;
        int chunk_no;
        int chunk_off;
+       int nchunks;
        struct rpcrdma_segment *ch;
        struct rpcrdma_write_array *arg_ary;
        struct rpcrdma_write_array *res_ary;
@@ -476,26 +477,27 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
                max_write = xprt->sc_max_sge * PAGE_SIZE;
 
        /* xdr offset starts at RPC message */
+       nchunks = ntohl(arg_ary->wc_nchunks);
        for (xdr_off = 0, chunk_no = 0;
-            xfer_len && chunk_no < arg_ary->wc_nchunks;
+            xfer_len && chunk_no < nchunks;
             chunk_no++) {
                u64 rs_offset;
                ch = &arg_ary->wc_array[chunk_no].wc_target;
-               write_len = min(xfer_len, ch->rs_length);
+               write_len = min(xfer_len, htonl(ch->rs_length));
 
                /* Prepare the reply chunk given the length actually
                 * written */
-               rs_offset = get_unaligned(&(ch->rs_offset));
+               xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset);
                svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
-                                           ch->rs_handle, rs_offset,
-                                           write_len);
+                                               ch->rs_handle, ch->rs_offset,
+                                               write_len);
                chunk_off = 0;
                while (write_len) {
                        int this_write;
 
                        this_write = min(write_len, max_write);
                        ret = send_write(xprt, rqstp,
-                                        ch->rs_handle,
+                                        ntohl(ch->rs_handle),
                                         rs_offset + chunk_off,
                                         xdr_off,
                                         this_write,
index 894cb42db91d6c9e2cb71a9ae0aa076db4573d96..73b428bef5986bd06b751bf45b3f3f7f6698fdd2 100644 (file)
@@ -51,6 +51,7 @@
 #include <rdma/rdma_cm.h>
 #include <linux/sunrpc/svc_rdma.h>
 #include <linux/export.h>
+#include "xprt_rdma.h"
 
 #define RPCDBG_FACILITY        RPCDBG_SVCXPRT
 
@@ -90,12 +91,6 @@ struct svc_xprt_class svc_rdma_class = {
        .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
 };
 
-/* WR context cache. Created in svc_rdma.c  */
-extern struct kmem_cache *svc_rdma_ctxt_cachep;
-
-/* Workqueue created in svc_rdma.c */
-extern struct workqueue_struct *svc_rdma_wq;
-
 struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
 {
        struct svc_rdma_op_ctxt *ctxt;
@@ -150,9 +145,6 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
        atomic_dec(&xprt->sc_ctxt_used);
 }
 
-/* Temporary NFS request map cache. Created in svc_rdma.c  */
-extern struct kmem_cache *svc_rdma_map_cachep;
-
 /*
  * Temporary NFS req mappings are shared across all transport
  * instances. These are short lived and should be bounded by the number
index 08c5d5a128fc44e835a6f6ac13f6b81a5387c889..9a66c95b5837159b8f3758795a48009bb6f8108a 100644 (file)
@@ -343,4 +343,11 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *);
  */
 int rpcrdma_marshal_req(struct rpc_rqst *);
 
+/* Temporary NFS request map cache. Created in svc_rdma.c  */
+extern struct kmem_cache *svc_rdma_map_cachep;
+/* WR context cache. Created in svc_rdma.c  */
+extern struct kmem_cache *svc_rdma_ctxt_cachep;
+/* Workqueue created in svc_rdma.c */
+extern struct workqueue_struct *svc_rdma_wq;
+
 #endif                         /* _LINUX_SUNRPC_XPRT_RDMA_H */
index 92bc5181dbebde6e82af566ed54f4ca04a61b857..890b03f8d8771ea325cf41be4f9bddd50a07fc12 100644 (file)
@@ -2475,6 +2475,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
 static struct rpc_xprt_ops bc_tcp_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xprt_release_xprt,
+       .rpcbind                = xs_local_rpcbind,
        .buf_alloc              = bc_malloc,
        .buf_free               = bc_free,
        .send_request           = bc_send_request,
index 98cffcb941ea6e319fd4bee04db7f06de379031b..a2af2e88daf3e094bc786f368ce4fe88d5b947d7 100644 (file)
@@ -2,4 +2,20 @@
 # Test for gcc 'asm goto' support
 # Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
 
-echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
+cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
+int main(void)
+{
+#ifdef __arm__
+       /*
+        * Not related to asm goto, but used by jump label
+        * and broken on some ARM GCC versions (see GCC Bug 48637).
+        */
+       static struct { int dummy; int state; } tp;
+       asm (".long %c0" :: "i" (&tp.state));
+#endif
+
+entry:
+       asm goto ("" :::: entry);
+       return 0;
+}
+END
index 7c69599a69e1c21560ff3cf7e1ea04690b3e039b..6327685c101e49cc720553c9db9f02da3fed1d24 100644 (file)
@@ -410,7 +410,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
                 * exec\0change_profile
                 */
                state = aa_dfa_null_transition(profile->file.dfa, state);
-               cp = change_profile_perms(profile, cxt->onexec->ns, name,
+               cp = change_profile_perms(profile, cxt->onexec->ns,
+                                         cxt->onexec->base.name,
                                          AA_MAY_ONEXEC, state);
 
                if (!(cp.allow & AA_MAY_ONEXEC))
index 3022c0f4f0dbc2878fdf09c3e318333bc3d685de..5d176f2530c9820873d57c082ff787c5eca38de5 100644 (file)
@@ -215,6 +215,8 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
        /* change_profile wasn't determined by ownership in old mapping */
        if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
                perms.allow |= AA_MAY_CHANGE_PROFILE;
+       if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
+               perms.allow |= AA_MAY_ONEXEC;
 
        return perms;
 }
index 30492990937595b420e3d01be4a6cc0f5448ff7f..15c6c567468b6f4a12d00b8a4f5756311ddbc532 100644 (file)
@@ -2147,7 +2147,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                fdt = files_fdtable(files);
                if (i >= fdt->max_fds)
                        break;
-               set = fdt->open_fds->fds_bits[j];
+               set = fdt->open_fds[j];
                if (!set)
                        continue;
                spin_unlock(&files->file_lock);
index 47fda963495ddc0c5fa8f0d36468dff014035764..005a91bcb200d0d12ac6c7727f516743ae330439 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/audit.h>
 #include <linux/lsm_audit.h>
 #include <linux/in6.h>
-#include <asm/system.h>
 #include "flask.h"
 #include "av_permissions.h"
 #include "security.h"
index b43813c9e049c9491cd37283c5f45bf494a6efcd..c220f314709cc1345792e4a4ddab28cd63a23177 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _SELINUX_XFRM_H_
 #define _SELINUX_XFRM_H_
 
+#include <net/flow.h>
+
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
                              struct xfrm_user_sec_ctx *sec_ctx);
 int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
index d1aa4218f1299ebccb813d0b8ef6c6fb9d8c3479..48d7c0aa5073d43897b126fdbc743f84350f1783 100644 (file)
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <sound/ac97_codec.h>
 #include <sound/pxa2xx-lib.h>
 
-#include <asm/irq.h>
+#include <mach/irqs.h>
 #include <mach/regs-ac97.h>
 #include <mach/audio.h>
 
index 3a39626a82d627943d0cec0f891fe130e1d5b60e..afef72c4f0d3a71f3cba405c5cf63884168e1efa 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
index 4fa1dbd8ee8381e1fbc4260c779cfecdea1d1923..f7c2bb08055d039bb48d9d84901e3b002ed7537e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/types.h>
 #include <linux/io.h>
 
 #include <sound/core.h>
@@ -467,15 +468,24 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev)
        snd_card_set_dev(card, &pdev->dev);
 
        if (pdata->dws.dma_dev) {
-               struct dw_dma_slave *dws = &pdata->dws;
                dma_cap_mask_t mask;
 
-               dws->tx_reg = regs->start + DAC_DATA;
-
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
 
-               dac->dma.chan = dma_request_channel(mask, filter, dws);
+               dac->dma.chan = dma_request_channel(mask, filter, &pdata->dws);
+               if (dac->dma.chan) {
+                       struct dma_slave_config dma_conf = {
+                               .dst_addr = regs->start + DAC_DATA,
+                               .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+                               .src_maxburst = 1,
+                               .dst_maxburst = 1,
+                               .direction = DMA_MEM_TO_DEV,
+                               .device_fc = false,
+                       };
+
+                       dmaengine_slave_config(dac->dma.chan, &dma_conf);
+               }
        }
        if (!pdata->dws.dma_dev || !dac->dma.chan) {
                dev_dbg(&pdev->dev, "DMA not available\n");
index 61dade6983582ce415afdbe3cf88d208bb628c46..115313ef54d67e7d10cc6b6d4295a53bf49e340d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/gpio.h>
+#include <linux/types.h>
 #include <linux/io.h>
 
 #include <sound/core.h>
@@ -1014,16 +1015,28 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
 
        if (cpu_is_at32ap7000()) {
                if (pdata->rx_dws.dma_dev) {
-                       struct dw_dma_slave *dws = &pdata->rx_dws;
                        dma_cap_mask_t mask;
 
-                       dws->rx_reg = regs->start + AC97C_CARHR + 2;
-
                        dma_cap_zero(mask);
                        dma_cap_set(DMA_SLAVE, mask);
 
                        chip->dma.rx_chan = dma_request_channel(mask, filter,
-                                                               dws);
+                                                               &pdata->rx_dws);
+                       if (chip->dma.rx_chan) {
+                               struct dma_slave_config dma_conf = {
+                                       .src_addr = regs->start + AC97C_CARHR +
+                                               2,
+                                       .src_addr_width =
+                                               DMA_SLAVE_BUSWIDTH_2_BYTES,
+                                       .src_maxburst = 1,
+                                       .dst_maxburst = 1,
+                                       .direction = DMA_DEV_TO_MEM,
+                                       .device_fc = false,
+                               };
+
+                               dmaengine_slave_config(chip->dma.rx_chan,
+                                               &dma_conf);
+                       }
 
                        dev_info(&chip->pdev->dev, "using %s for DMA RX\n",
                                dev_name(&chip->dma.rx_chan->dev->device));
@@ -1031,16 +1044,28 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
                }
 
                if (pdata->tx_dws.dma_dev) {
-                       struct dw_dma_slave *dws = &pdata->tx_dws;
                        dma_cap_mask_t mask;
 
-                       dws->tx_reg = regs->start + AC97C_CATHR + 2;
-
                        dma_cap_zero(mask);
                        dma_cap_set(DMA_SLAVE, mask);
 
                        chip->dma.tx_chan = dma_request_channel(mask, filter,
-                                                               dws);
+                                                               &pdata->tx_dws);
+                       if (chip->dma.tx_chan) {
+                               struct dma_slave_config dma_conf = {
+                                       .dst_addr = regs->start + AC97C_CATHR +
+                                               2,
+                                       .dst_addr_width =
+                                               DMA_SLAVE_BUSWIDTH_2_BYTES,
+                                       .src_maxburst = 1,
+                                       .dst_maxburst = 1,
+                                       .direction = DMA_MEM_TO_DEV,
+                                       .device_fc = false,
+                               };
+
+                               dmaengine_slave_config(chip->dma.tx_chan,
+                                               &dma_conf);
+                       }
 
                        dev_info(&chip->pdev->dev, "using %s for DMA TX\n",
                                dev_name(&chip->dma.tx_chan->dev->device));
index a1a962d7f67d3a07e77cf1d0a36b791116ca83cf..75ad0cd0c0ab8b31b608c93dbf87ee3c07bf63c7 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include <linux/poll.h>
index 12ba28e7b933d419b56ae4f74381b05073197c5b..92ca5bee1860aa9ea87665c878688d431b337602 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/hardware/iomd.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "sound_config.h"
 #include "vidc.h"
index 52468742d9f240650376da69b368927c095041e7..24c430f721d4b07f0aed96eaa2713271273c5e8b 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 
 #include "sound_config.h"
 #include "waveartist.h"
index c5cef113c2090cec68732398384ee8b1fd6d592f..d3fbd0d76c37149c3e654329cabed329b65ead59 100644 (file)
@@ -30,7 +30,6 @@ HPI Operating System Specific macros for Linux Kernel driver
 #define HPI_BUILD_KERNEL_MODE
 
 #include <linux/io.h>
-#include <asm/system.h>
 #include <linux/ioctl.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 8afd8b5d1ac73420e408427fb8536f96d0384db7..4439636971eb4c4c215ba49cff8c0b6015b873b2 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <sound/core.h>
 #include <sound/initval.h>
index e43c8fa2788b34062b5601066b112c6c667e5c67..6b818de2fc03344e6c532067b252655b32c99819 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dmaengine.h>
+#include <linux/types.h>
 
 #include <sound/core.h>
 #include <sound/initval.h>
@@ -58,6 +59,8 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ret)
                return ret;
 
+       slave_config.device_fc = false;
+
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                slave_config.dst_addr = dma_params->dma_addr;
                slave_config.dst_maxburst = dma_params->burstsize;
index 4800d5fe568dcdd38adbbe424a1c0e595139775b..06ea2744cc88f161e8d3508137747ee7d5958669 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
index 0193e595d415da8b82e7bf383b243dbdba25f88e..5cfcc655e95ffe33670c68e0e998e7a1ceec17af 100644 (file)
@@ -130,7 +130,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
        sg_dma_len(&sg) = size;
        sg_dma_address(&sg) = buff;
 
-       desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
+       desc = dmaengine_prep_slave_sg(siu_stream->chan,
                &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dev_err(dev, "Failed to allocate a dma descriptor\n");
@@ -180,7 +180,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
        sg_dma_len(&sg) = size;
        sg_dma_address(&sg) = buff;
 
-       desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
+       desc = dmaengine_prep_slave_sg(siu_stream->chan,
                &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (!desc) {
                dev_err(dev, "Failed to allocate dma descriptor\n");
index 21554611557c380ca391a9c384407a9744a056a1..b609d2c64c555b0346b6c9cb7ade29cb95d6277f 100644 (file)
@@ -132,7 +132,7 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr)
        sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf_dma_addr)),
                    dmadata->frag_bytes, buf_dma_addr & (PAGE_SIZE - 1));
        sg_dma_address(&sg) = buf_dma_addr;
-       desc = chan->device->device_prep_slave_sg(chan, &sg, 1,
+       desc = dmaengine_prep_slave_sg(chan, &sg, 1,
                dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
                DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
index e8a03aceceb11fe88b5552a0952431866213ee42..a93e06cfcc2a2f6218a7e7a4397510efa20fc2a3 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 #
+OUTPUT=./
+ifeq ("$(origin O)", "command line")
+       OUTPUT := $(O)/
+endif
+
+ifneq ($(OUTPUT),)
+# check that the output directory actually exists
+OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
+$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
+endif
 
 # --- CONFIGURATION BEGIN ---
 
@@ -87,6 +97,7 @@ AR = $(CROSS)ar
 STRIP = $(CROSS)strip
 RANLIB = $(CROSS)ranlib
 HOSTCC = gcc
+MKDIR = mkdir
 
 
 # Now we set up the build system
@@ -95,7 +106,7 @@ HOSTCC = gcc
 # set up PWD so that older versions of make will work with our build.
 PWD = $(shell pwd)
 
-GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;}
+GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; done;}
 
 export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
 
@@ -122,15 +133,18 @@ UTIL_OBJS =  utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
        utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
        utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
 
+UTIL_SRC := $(UTIL_OBJS:.o=.c)
+
+UTIL_OBJS := $(addprefix $(OUTPUT),$(UTIL_OBJS))
+
 UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
        utils/helpers/bitmask.h \
        utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
 
-UTIL_SRC := $(UTIL_OBJS:.o=.c)
-
 LIB_HEADERS =  lib/cpufreq.h lib/sysfs.h
 LIB_SRC =      lib/cpufreq.c lib/sysfs.c
 LIB_OBJS =     lib/cpufreq.o lib/sysfs.o
+LIB_OBJS :=    $(addprefix $(OUTPUT),$(LIB_OBJS))
 
 CFLAGS +=      -pipe
 
@@ -168,83 +182,90 @@ endif
 
 # the actual make rules
 
-all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH)
+all: libcpupower $(OUTPUT)cpupower $(COMPILE_NLS) $(COMPILE_BENCH)
 
-lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
+$(OUTPUT)lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
        $(ECHO) "  CC      " $@
        $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
 
-libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
+$(OUTPUT)libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
        $(ECHO) "  LD      " $@
        $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \
                -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
-       @ln -sf $libcpupower.so
-       @ln -sf $libcpupower.so.$(LIB_MIN)
+       @ln -sf $(@F) $(OUTPUT)libcpupower.so
+       @ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MIN)
 
-libcpupower: libcpupower.so.$(LIB_MAJ)
+libcpupower: $(OUTPUT)libcpupower.so.$(LIB_MAJ)
 
 # Let all .o files depend on its .c file and all headers
 # Might be worth to put this into utils/Makefile at some point of time
 $(UTIL_OBJS): $(UTIL_HEADERS)
 
-.c.o:
+$(OUTPUT)%.o: %.c
        $(ECHO) "  CC      " $@
        $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c
 
-cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ)
+$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
        $(ECHO) "  CC      " $@
-       $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS)
+       $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -lrt -lpci -L$(OUTPUT) -o $@
        $(QUIET) $(STRIPCMD) $@
 
-po/$(PACKAGE).pot: $(UTIL_SRC)
+$(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC)
        $(ECHO) "  GETTEXT " $@
        $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \
-               --keyword=_ --keyword=N_ $(UTIL_SRC) && \
-       test -f $(PACKAGE).po && \
-       mv -f $(PACKAGE).po po/$(PACKAGE).pot
+               --keyword=_ --keyword=N_ $(UTIL_SRC) -p $(@D) -o $(@F)
 
-po/%.gmo: po/%.po
+$(OUTPUT)po/%.gmo: po/%.po
        $(ECHO) "  MSGFMT  " $@
        $(QUIET) msgfmt -o $@ po/$*.po
 
 create-gmo: ${GMO_FILES}
 
-update-po: po/$(PACKAGE).pot
+update-po: $(OUTPUT)po/$(PACKAGE).pot
        $(ECHO) "  MSGMRG  " $@
        $(QUIET) @for HLANG in $(LANGUAGES); do \
                echo -n "Updating $$HLANG "; \
-               if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \
-                  po/$$HLANG.new.po; then \
-                       mv -f po/$$HLANG.new.po po/$$HLANG.po; \
+               if msgmerge po/$$HLANG.po $< -o \
+                  $(OUTPUT)po/$$HLANG.new.po; then \
+                       mv -f $(OUTPUT)po/$$HLANG.new.po $(OUTPUT)po/$$HLANG.po; \
                else \
                        echo "msgmerge for $$HLANG failed!"; \
-                       rm -f po/$$HLANG.new.po; \
+                       rm -f $(OUTPUT)po/$$HLANG.new.po; \
                fi; \
        done;
 
-compile-bench: libcpupower.so.$(LIB_MAJ)
-       @V=$(V) confdir=$(confdir) $(MAKE) -C bench
+compile-bench: $(OUTPUT)libcpupower.so.$(LIB_MAJ)
+       @V=$(V) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT)
+
+# we compile into subdirectories. if the target directory is not the
+# source directory, they might not exists. So we depend the various
+# files onto their directories.
+DIRECTORY_DEPS = $(LIB_OBJS) $(UTIL_OBJS) $(GMO_FILES)
+$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
+
+# In the second step, we make a rule to actually create these directories
+$(sort $(dir $(DIRECTORY_DEPS))):
+       $(ECHO) "  MKDIR      " $@
+       $(QUIET) $(MKDIR) -p $@ 2>/dev/null
 
 clean:
-       -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
+       -find $(OUTPUT) \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
         | xargs rm -f
-       -rm -f $(UTIL_BINS)
-       -rm -f $(IDLE_OBJS)
-       -rm -f cpupower
-       -rm -f libcpupower.so*
-       -rm -rf po/*.gmo po/*.pot
-       $(MAKE) -C bench clean
+       -rm -f $(OUTPUT)cpupower
+       -rm -f $(OUTPUT)libcpupower.so*
+       -rm -rf $(OUTPUT)po/*.{gmo,pot}
+       $(MAKE) -C bench O=$(OUTPUT) clean
 
 
 install-lib:
        $(INSTALL) -d $(DESTDIR)${libdir}
-       $(CP) libcpupower.so* $(DESTDIR)${libdir}/
+       $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/
        $(INSTALL) -d $(DESTDIR)${includedir}
        $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
 
 install-tools:
        $(INSTALL) -d $(DESTDIR)${bindir}
-       $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir}
+       $(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
 
 install-man:
        $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
@@ -257,13 +278,13 @@ install-man:
 install-gmo:
        $(INSTALL) -d $(DESTDIR)${localedir}
        for HLANG in $(LANGUAGES); do \
-               echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \
-               $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
+               echo '$(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \
+               $(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
        done;
 
 install-bench:
        @#DESTDIR must be set from outside to survive
-       @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install
+       @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) install
 
 install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
 
index 2b67606fc3e30c9648c16ab0d15b015f30cceb2a..7ec7021a29cd8d37a9abf4ecc08c396d50368501 100644 (file)
@@ -1,29 +1,36 @@
-LIBS = -L../ -lm -lcpupower
+OUTPUT := ./
+ifeq ("$(origin O)", "command line")
+ifneq ($(O),)
+       OUTPUT := $(O)/
+endif
+endif
 
-OBJS = main.o parse.o system.o benchmark.o
+LIBS = -L../ -L$(OUTPUT) -lm -lcpupower
+
+OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o
 CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
 
-%.o : %.c
+$(OUTPUT)%.o : %.c
        $(ECHO) "  CC      " $@
        $(QUIET) $(CC) -c $(CFLAGS) $< -o $@
 
-cpufreq-bench: $(OBJS)
+$(OUTPUT)cpufreq-bench: $(OBJS)
        $(ECHO) "  CC      " $@
        $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS)
 
-all: cpufreq-bench
+all: $(OUTPUT)cpufreq-bench
 
 install:
        mkdir -p $(DESTDIR)/$(sbindir)
        mkdir -p $(DESTDIR)/$(bindir)
        mkdir -p $(DESTDIR)/$(docdir)
        mkdir -p $(DESTDIR)/$(confdir)
-       install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
+       install -m 755 $(OUTPUT)cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
        install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh
        install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH
        install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh
        install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf
 
 clean:
-       rm -f *.o
-       rm -f cpufreq-bench
+       rm -f $(OUTPUT)*.o
+       rm -f $(OUTPUT)cpufreq-bench
index d08cc1ead9bc973e6947829b37fac3b43b368744..3ba158f0e2871dee52cd7b2820706b0eca68eb9e 100644 (file)
@@ -1,20 +1,38 @@
+OUTPUT=./
+ifeq ("$(origin O)", "command line")
+       OUTPUT := $(O)/
+endif
+
+DESTDIR =
+bindir  = /usr/bin
+
+INSTALL = /usr/bin/install
+
+
 default: all
 
-centrino-decode: centrino-decode.c
-       $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c
+$(OUTPUT)centrino-decode: centrino-decode.c
+       $(CC) $(CFLAGS) -o $@ centrino-decode.c
 
-dump_psb: dump_psb.c
-       $(CC) $(CFLAGS) -o dump_psb dump_psb.c
+$(OUTPUT)dump_psb: dump_psb.c
+       $(CC) $(CFLAGS) -o $@ dump_psb.c
 
-intel_gsic: intel_gsic.c
-       $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c
+$(OUTPUT)intel_gsic: intel_gsic.c
+       $(CC) $(CFLAGS) -o $@ -llrmi intel_gsic.c
 
-powernow-k8-decode: powernow-k8-decode.c
-       $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c
+$(OUTPUT)powernow-k8-decode: powernow-k8-decode.c
+       $(CC) $(CFLAGS) -o $@ powernow-k8-decode.c
 
-all: centrino-decode dump_psb intel_gsic powernow-k8-decode
+all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode
 
 clean:
-       rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode
+       rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode}
+
+install:
+       $(INSTALL) -d $(DESTDIR)${bindir}
+       $(INSTALL) $(OUTPUT)centrino-decode $(DESTDIR)${bindir}
+       $(INSTALL) $(OUTPUT)powernow-k8-decode $(DESTDIR)${bindir}
+       $(INSTALL) $(OUTPUT)dump_psb $(DESTDIR)${bindir}
+       $(INSTALL) $(OUTPUT)intel_gsic $(DESTDIR)${bindir}
 
-.PHONY: all default clean
+.PHONY: all default clean install
index 3326217dd31158d24446213d709a3f8cb5b7002c..1c52145267166a076585e099ad478caac9c154a3 100644 (file)
@@ -1,14 +1,30 @@
+OUTPUT=./
+ifeq ("$(origin O)", "command line")
+       OUTPUT := $(O)/
+endif
+
+DESTDIR =
+bindir  = /usr/bin
+
+INSTALL = /usr/bin/install
+
+
 default: all
 
-centrino-decode: ../i386/centrino-decode.c
+$(OUTPUT)centrino-decode: ../i386/centrino-decode.c
        $(CC) $(CFLAGS) -o $@ $<
 
-powernow-k8-decode: ../i386/powernow-k8-decode.c
+$(OUTPUT)powernow-k8-decode: ../i386/powernow-k8-decode.c
        $(CC) $(CFLAGS) -o $@ $<
 
-all: centrino-decode powernow-k8-decode
+all: $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode
 
 clean:
-       rm -rf centrino-decode powernow-k8-decode
+       rm -rf $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode
+
+install:
+       $(INSTALL) -d $(DESTDIR)${bindir}
+       $(INSTALL) $(OUTPUT)centrino-decode $(DESTDIR)${bindir}
+       $(INSTALL) $(OUTPUT)powernow-k8-decode $(DESTDIR)${bindir}
 
-.PHONY: all default clean
+.PHONY: all default clean install
index bb60a8d1e45abb0e4685792ad02ca187893cac8a..4a1918ea8f9c2d4d1b45d2626d5f6c3a662d1ffc 100644 (file)
@@ -1,4 +1,4 @@
-.TH "cpupower-frequency-info" "1" "0.1" "Mattia Dongili" ""
+.TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual"
 .SH "NAME"
 .LP 
 cpupower frequency\-info \- Utility to retrieve cpufreq kernel information
@@ -50,8 +50,6 @@ Prints out information like provided by the /proc/cpufreq interface in 2.4. and
 \fB\-m\fR \fB\-\-human\fR
 human\-readable output for the \-f, \-w, \-s and \-y parameters.
 .TP  
-\fB\-h\fR \fB\-\-help\fR
-Prints out the help screen.
 .SH "REMARKS"
 .LP 
 By default only values of core zero are displayed. How to display settings of
index 685f469093ad200c93e2e9feb3e23dcaec863a5a..3eacc8d03d1a1e12b167c3c1926f9851740e1578 100644 (file)
@@ -1,4 +1,4 @@
-.TH "cpupower-freqency-set" "1" "0.1" "Mattia Dongili" ""
+.TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual"
 .SH "NAME"
 .LP 
 cpupower frequency\-set \- A small tool which allows to modify cpufreq settings.
@@ -26,8 +26,6 @@ specific frequency to be set. Requires userspace governor to be available and lo
 \fB\-r\fR \fB\-\-related\fR
 modify all hardware-related CPUs at the same time
 .TP 
-\fB\-h\fR \fB\-\-help\fR
-Prints out the help screen.
 .SH "REMARKS"
 .LP 
 By default values are applied on all cores. How to modify single core
diff --git a/tools/power/cpupower/man/cpupower-idle-info.1 b/tools/power/cpupower/man/cpupower-idle-info.1
new file mode 100644 (file)
index 0000000..4178eff
--- /dev/null
@@ -0,0 +1,90 @@
+.TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual"
+.SH "NAME"
+.LP
+cpupower idle\-info \- Utility to retrieve cpu idle kernel information
+.SH "SYNTAX"
+.LP
+cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
+.SH "DESCRIPTION"
+.LP
+A tool which prints out per cpu idle information helpful to developers and interested users.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-f\fR \fB\-\-silent\fR
+Only print a summary of all available C-states in the system.
+.TP
+\fB\-e\fR \fB\-\-proc\fR
+deprecated.
+Prints out idle information in old /proc/acpi/processor/*/power format. This
+interface has been removed from the kernel for quite some time, do not let
+further code depend on this option, best do not use it.
+
+.SH IDLE\-INFO DESCRIPTIONS
+CPU sleep state statistics and descriptions are retrieved from sysfs files,
+exported by the cpuidle kernel subsystem. The kernel only updates these
+statistics when it enters or leaves an idle state, therefore on a very idle or
+a very busy system, these statistics may not be accurate. They still provide a
+good overview about the usage and availability of processor sleep states on
+the platform.
+
+Be aware that the sleep states as exported by the hardware or BIOS and used by
+the Linux kernel may not exactly reflect the capabilities of the
+processor. This often is the case on the X86 architecture when the acpi_idle
+driver is used. It is also possible that the hardware overrules the kernel
+requests, due to internal activity monitors or other reasons.
+On recent X86 platforms it is often possible to read out hardware registers
+which monitor the duration of sleep states the processor resided in. The
+cpupower monitor tool (cpupower\-monitor(1)) can be used to show real sleep
+state residencies. Please refer to the architecture specific description
+section below.
+
+.SH IDLE\-INFO ARCHITECTURE SPECIFIC DESCRIPTIONS
+.SS "X86"
+POLL idle state
+
+If cpuidle is active, X86 platforms have one special idle state.
+The POLL idle state is not a real idle state, it does not save any
+power. Instead, a busy\-loop is executed doing nothing for a short period of
+time. This state is used if the kernel knows that work has to be processed
+very soon and entering any real hardware idle state may result in a slight
+performance penalty.
+
+There exist two different cpuidle drivers on the X86 architecture platform:
+
+"acpi_idle" cpuidle driver
+
+The acpi_idle cpuidle driver retrieves available sleep states (C\-states) from
+the ACPI BIOS tables (from the _CST ACPI function on recent platforms or from
+the FADT BIOS table on older ones).
+The C1 state is not retrieved from ACPI tables. If the C1 state is entered,
+the kernel will call the hlt instruction (or mwait on Intel).
+
+"intel_idle" cpuidle driver
+
+In kernel 2.6.36 the intel_idle driver was introduced.
+It only serves recent Intel CPUs (Nehalem, Westmere, Sandybridge, Atoms or
+newer). On older Intel CPUs the acpi_idle driver is still used (if the BIOS
+provides C\-state ACPI tables).
+The intel_idle driver knows the sleep state capabilities of the processor and
+ignores ACPI BIOS exported processor sleep states tables.
+
+.SH "REMARKS"
+.LP
+By default only values of core zero are displayed. How to display settings of
+other cores is described in the cpupower(1) manpage in the \-\-cpu option
+section.
+.SH REFERENCES
+http://www.acpi.info/spec.htm
+.SH "FILES"
+.nf
+\fI/sys/devices/system/cpu/cpu*/cpuidle/state*\fP
+\fI/sys/devices/system/cpu/cpuidle/*\fP
+.fi
+.SH "AUTHORS"
+.nf
+Thomas Renninger <trenn@suse.de>
+.fi
+.SH "SEE ALSO"
+.LP
+cpupower(1), cpupower\-monitor(1), cpupower\-info(1), cpupower\-set(1)
index d5cfa265c3d3c93e53043bedb6fd2cea131759c0..1141c2073719d266fe4bf7ea65d9692fc9ff79a0 100644 (file)
@@ -107,7 +107,7 @@ Deepest package sleep states may in reality show up as machine/platform wide
 sleep states and can only be entered if all cores are idle. Look up Intel
 manuals (some are provided in the References section) for further details.
 
-.SS "Ontario" "Liano"
+.SS "Fam_12h" "Fam_14h"
 AMD laptop and desktop processor (family 12h and 14h) sleep state counters.
 The registers are accessed via PCI and therefore can still be read out while
 cores have been offlined.
index b028267c1376a6c63c455bbdabeb5c36218aee2a..8145af5f93a674b861f907d05639b06bb637ffb6 100644 (file)
@@ -35,17 +35,9 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
                printf(_("CPU %u: Can't read idle state info\n"), cpu);
                return;
        }
-       tmp = sysfs_get_idlestate_name(cpu, idlestates - 1);
-       if (!tmp) {
-               printf(_("Could not determine max idle state %u\n"),
-                      idlestates - 1);
-               return;
-       }
-
        printf(_("Number of idle states: %d\n"), idlestates);
-
        printf(_("Available idle states:"));
-       for (idlestate = 1; idlestate < idlestates; idlestate++) {
+       for (idlestate = 0; idlestate < idlestates; idlestate++) {
                tmp = sysfs_get_idlestate_name(cpu, idlestate);
                if (!tmp)
                        continue;
@@ -57,7 +49,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
        if (!verbose)
                return;
 
-       for (idlestate = 1; idlestate < idlestates; idlestate++) {
+       for (idlestate = 0; idlestate < idlestates; idlestate++) {
                tmp = sysfs_get_idlestate_name(cpu, idlestate);
                if (!tmp)
                        continue;
index 87d5605bdda82394a692b51104bcdc9ff32a20d9..6437ef39aeea61fe592d11d5a022730a8b46a6dd 100644 (file)
@@ -112,14 +112,12 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family,
 int amd_pci_get_num_boost_states(int *active, int *states)
 {
        struct pci_access *pci_acc;
-       int vendor_id = 0x1022;
-       int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0};
        struct pci_dev *device;
        uint8_t val = 0;
 
        *active = *states = 0;
 
-       device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids);
+       device = pci_slot_func_init(&pci_acc, 0x18, 4);
 
        if (device == NULL)
                return -ENODEV;
index 2747e738efb04d3fa1a53e7686162240cfc7a7ec..2eb584cf2f55d69ef1738d2beb40030713fb3f92 100644 (file)
@@ -66,8 +66,8 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
 #define CPUPOWER_CAP_AMD_CBP           0x00000004
 #define CPUPOWER_CAP_PERF_BIAS         0x00000008
 #define CPUPOWER_CAP_HAS_TURBO_RATIO   0x00000010
-#define CPUPOWER_CAP_IS_SNB            0x00000011
-#define CPUPOWER_CAP_INTEL_IDA         0x00000012
+#define CPUPOWER_CAP_IS_SNB            0x00000020
+#define CPUPOWER_CAP_INTEL_IDA         0x00000040
 
 #define MAX_HW_PSTATES 10
 
@@ -132,8 +132,11 @@ extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
 
 /* PCI stuff ****************************/
 extern int amd_pci_get_num_boost_states(int *active, int *states);
-extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
-                                   int *dev_ids);
+extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain,
+                                   int bus, int slot, int func, int vendor,
+                                   int dev);
+extern struct pci_dev *pci_slot_func_init(struct pci_access **pacc,
+                                             int slot, int func);
 
 /* PCI stuff ****************************/
 
index cd2eb6fe41c457cd9089414943f71c20e0806fd4..9690798e64463bc2ef7178cb35078406d0b5971d 100644 (file)
  * **pacc : if a valid pci_dev is returned
  *         *pacc must be passed to pci_acc_cleanup to free it
  *
- * vendor_id : the pci vendor id matching the pci device to access
- * dev_ids :   device ids matching the pci device to access
+ * domain: domain
+ * bus:    bus
+ * slot:   slot
+ * func:   func
+ * vendor: vendor
+ * device: device
+ * Pass -1 for one of the six above to match any
  *
  * Returns :
  * struct pci_dev which can be used with pci_{read,write}_* functions
  *                to access the PCI config space of matching pci devices
  */
-struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
-                                   int *dev_ids)
+struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
+                            int slot, int func, int vendor, int dev)
 {
-       struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0};
+       struct pci_filter filter_nb_link = { domain, bus, slot, func,
+                                            vendor, dev };
        struct pci_dev *device;
-       unsigned int i;
 
        *pacc = pci_alloc();
        if (*pacc == NULL)
@@ -31,14 +36,20 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
        pci_init(*pacc);
        pci_scan_bus(*pacc);
 
-       for (i = 0; dev_ids[i] != 0; i++) {
-               filter_nb_link.device = dev_ids[i];
-               for (device = (*pacc)->devices; device; device = device->next) {
-                       if (pci_filter_match(&filter_nb_link, device))
-                               return device;
-               }
+       for (device = (*pacc)->devices; device; device = device->next) {
+               if (pci_filter_match(&filter_nb_link, device))
+                       return device;
        }
        pci_cleanup(*pacc);
        return NULL;
 }
+
+/* Typically one wants to get a specific slot(device)/func of the root domain
+   and bus */
+struct pci_dev *pci_slot_func_init(struct pci_access **pacc, int slot,
+                                      int func)
+{
+       return pci_acc_init(pacc, 0, 0, slot, func, -1, -1);
+}
+
 #endif /* defined(__i386__) || defined(__x86_64__) */
index 202e555988becfbe7f52d08e20b7b85c1d238729..2116df9ad83254eb0a7a37246b83f959e669b7f5 100644 (file)
@@ -20,8 +20,6 @@
 #include "idle_monitor/cpupower-monitor.h"
 #include "helpers/helpers.h"
 
-/******** PCI parts could go into own file and get shared ***************/
-
 #define PCI_NON_PC0_OFFSET     0xb0
 #define PCI_PC1_OFFSET         0xb4
 #define PCI_PC6_OFFSET         0xb8
@@ -82,10 +80,7 @@ static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
 };
 
 static struct pci_access *pci_acc;
-static int pci_vendor_id = 0x1022;
-static int pci_dev_ids[2] = {0x1716, 0};
 static struct pci_dev *amd_fam14h_pci_dev;
-
 static int nbp1_entered;
 
 struct timespec start_time;
@@ -286,13 +281,13 @@ struct cpuidle_monitor *amd_fam14h_register(void)
        if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
                return NULL;
 
-       if (cpupower_cpu_info.family == 0x14) {
-               if (cpu_count <= 0 || cpu_count > 2) {
-                       fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n",
-                               cpu_count);
-                       return NULL;
-               }
-       else
+       if (cpupower_cpu_info.family == 0x14)
+               strncpy(amd_fam14h_monitor.name, "Fam_14h",
+                       MONITOR_NAME_LEN - 1);
+       else if (cpupower_cpu_info.family == 0x12)
+               strncpy(amd_fam14h_monitor.name, "Fam_12h",
+                       MONITOR_NAME_LEN - 1);
+       else
                return NULL;
 
        /* We do not alloc for nbp1 machine wide counter */
@@ -303,7 +298,9 @@ struct cpuidle_monitor *amd_fam14h_register(void)
                                              sizeof(unsigned long long));
        }
 
-       amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids);
+       /* We need PCI device: Slot 18, Func 6, compare with BKDG
+          for fam 12h/14h */
+       amd_fam14h_pci_dev = pci_slot_func_init(&pci_acc, 0x18, 6);
        if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
                return NULL;
 
@@ -325,7 +322,7 @@ static void amd_fam14h_unregister(void)
 }
 
 struct cpuidle_monitor amd_fam14h_monitor = {
-       .name                   = "Ontario",
+       .name                   = "",
        .hw_states              = amd_fam14h_cstates,
        .hw_states_num          = AMD_FAM14H_STATE_NUM,
        .start                  = amd_fam14h_start,
diff --git a/tools/slub/slabinfo.c b/tools/slub/slabinfo.c
deleted file mode 100644 (file)
index 164cbcf..0000000
+++ /dev/null
@@ -1,1393 +0,0 @@
-/*
- * Slabinfo: Tool to get reports about slabs
- *
- * (C) 2007 sgi, Christoph Lameter
- * (C) 2011 Linux Foundation, Christoph Lameter
- *
- * Compile with:
- *
- * gcc -o slabinfo slabinfo.c
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <strings.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <getopt.h>
-#include <regex.h>
-#include <errno.h>
-
-#define MAX_SLABS 500
-#define MAX_ALIASES 500
-#define MAX_NODES 1024
-
-struct slabinfo {
-       char *name;
-       int alias;
-       int refs;
-       int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
-       int hwcache_align, object_size, objs_per_slab;
-       int sanity_checks, slab_size, store_user, trace;
-       int order, poison, reclaim_account, red_zone;
-       unsigned long partial, objects, slabs, objects_partial, objects_total;
-       unsigned long alloc_fastpath, alloc_slowpath;
-       unsigned long free_fastpath, free_slowpath;
-       unsigned long free_frozen, free_add_partial, free_remove_partial;
-       unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill;
-       unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
-       unsigned long deactivate_to_head, deactivate_to_tail;
-       unsigned long deactivate_remote_frees, order_fallback;
-       unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
-       unsigned long alloc_node_mismatch, deactivate_bypass;
-       unsigned long cpu_partial_alloc, cpu_partial_free;
-       int numa[MAX_NODES];
-       int numa_partial[MAX_NODES];
-} slabinfo[MAX_SLABS];
-
-struct aliasinfo {
-       char *name;
-       char *ref;
-       struct slabinfo *slab;
-} aliasinfo[MAX_ALIASES];
-
-int slabs = 0;
-int actual_slabs = 0;
-int aliases = 0;
-int alias_targets = 0;
-int highest_node = 0;
-
-char buffer[4096];
-
-int show_empty = 0;
-int show_report = 0;
-int show_alias = 0;
-int show_slab = 0;
-int skip_zero = 1;
-int show_numa = 0;
-int show_track = 0;
-int show_first_alias = 0;
-int validate = 0;
-int shrink = 0;
-int show_inverted = 0;
-int show_single_ref = 0;
-int show_totals = 0;
-int sort_size = 0;
-int sort_active = 0;
-int set_debug = 0;
-int show_ops = 0;
-int show_activity = 0;
-
-/* Debug options */
-int sanity = 0;
-int redzone = 0;
-int poison = 0;
-int tracking = 0;
-int tracing = 0;
-
-int page_size;
-
-regex_t pattern;
-
-static void fatal(const char *x, ...)
-{
-       va_list ap;
-
-       va_start(ap, x);
-       vfprintf(stderr, x, ap);
-       va_end(ap);
-       exit(EXIT_FAILURE);
-}
-
-static void usage(void)
-{
-       printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n"
-               "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
-               "-a|--aliases           Show aliases\n"
-               "-A|--activity          Most active slabs first\n"
-               "-d<options>|--debug=<options> Set/Clear Debug options\n"
-               "-D|--display-active    Switch line format to activity\n"
-               "-e|--empty             Show empty slabs\n"
-               "-f|--first-alias       Show first alias\n"
-               "-h|--help              Show usage information\n"
-               "-i|--inverted          Inverted list\n"
-               "-l|--slabs             Show slabs\n"
-               "-n|--numa              Show NUMA information\n"
-               "-o|--ops               Show kmem_cache_ops\n"
-               "-s|--shrink            Shrink slabs\n"
-               "-r|--report            Detailed report on single slabs\n"
-               "-S|--Size              Sort by size\n"
-               "-t|--tracking          Show alloc/free information\n"
-               "-T|--Totals            Show summary information\n"
-               "-v|--validate          Validate slabs\n"
-               "-z|--zero              Include empty slabs\n"
-               "-1|--1ref              Single reference\n"
-               "\nValid debug options (FZPUT may be combined)\n"
-               "a / A          Switch on all debug options (=FZUP)\n"
-               "-              Switch off all debug options\n"
-               "f / F          Sanity Checks (SLAB_DEBUG_FREE)\n"
-               "z / Z          Redzoning\n"
-               "p / P          Poisoning\n"
-               "u / U          Tracking\n"
-               "t / T          Tracing\n"
-       );
-}
-
-static unsigned long read_obj(const char *name)
-{
-       FILE *f = fopen(name, "r");
-
-       if (!f)
-               buffer[0] = 0;
-       else {
-               if (!fgets(buffer, sizeof(buffer), f))
-                       buffer[0] = 0;
-               fclose(f);
-               if (buffer[strlen(buffer)] == '\n')
-                       buffer[strlen(buffer)] = 0;
-       }
-       return strlen(buffer);
-}
-
-
-/*
- * Get the contents of an attribute
- */
-static unsigned long get_obj(const char *name)
-{
-       if (!read_obj(name))
-               return 0;
-
-       return atol(buffer);
-}
-
-static unsigned long get_obj_and_str(const char *name, char **x)
-{
-       unsigned long result = 0;
-       char *p;
-
-       *x = NULL;
-
-       if (!read_obj(name)) {
-               x = NULL;
-               return 0;
-       }
-       result = strtoul(buffer, &p, 10);
-       while (*p == ' ')
-               p++;
-       if (*p)
-               *x = strdup(p);
-       return result;
-}
-
-static void set_obj(struct slabinfo *s, const char *name, int n)
-{
-       char x[100];
-       FILE *f;
-
-       snprintf(x, 100, "%s/%s", s->name, name);
-       f = fopen(x, "w");
-       if (!f)
-               fatal("Cannot write to %s\n", x);
-
-       fprintf(f, "%d\n", n);
-       fclose(f);
-}
-
-static unsigned long read_slab_obj(struct slabinfo *s, const char *name)
-{
-       char x[100];
-       FILE *f;
-       size_t l;
-
-       snprintf(x, 100, "%s/%s", s->name, name);
-       f = fopen(x, "r");
-       if (!f) {
-               buffer[0] = 0;
-               l = 0;
-       } else {
-               l = fread(buffer, 1, sizeof(buffer), f);
-               buffer[l] = 0;
-               fclose(f);
-       }
-       return l;
-}
-
-
-/*
- * Put a size string together
- */
-static int store_size(char *buffer, unsigned long value)
-{
-       unsigned long divisor = 1;
-       char trailer = 0;
-       int n;
-
-       if (value > 1000000000UL) {
-               divisor = 100000000UL;
-               trailer = 'G';
-       } else if (value > 1000000UL) {
-               divisor = 100000UL;
-               trailer = 'M';
-       } else if (value > 1000UL) {
-               divisor = 100;
-               trailer = 'K';
-       }
-
-       value /= divisor;
-       n = sprintf(buffer, "%ld",value);
-       if (trailer) {
-               buffer[n] = trailer;
-               n++;
-               buffer[n] = 0;
-       }
-       if (divisor != 1) {
-               memmove(buffer + n - 2, buffer + n - 3, 4);
-               buffer[n-2] = '.';
-               n++;
-       }
-       return n;
-}
-
-static void decode_numa_list(int *numa, char *t)
-{
-       int node;
-       int nr;
-
-       memset(numa, 0, MAX_NODES * sizeof(int));
-
-       if (!t)
-               return;
-
-       while (*t == 'N') {
-               t++;
-               node = strtoul(t, &t, 10);
-               if (*t == '=') {
-                       t++;
-                       nr = strtoul(t, &t, 10);
-                       numa[node] = nr;
-                       if (node > highest_node)
-                               highest_node = node;
-               }
-               while (*t == ' ')
-                       t++;
-       }
-}
-
-static void slab_validate(struct slabinfo *s)
-{
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       set_obj(s, "validate", 1);
-}
-
-static void slab_shrink(struct slabinfo *s)
-{
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       set_obj(s, "shrink", 1);
-}
-
-int line = 0;
-
-static void first_line(void)
-{
-       if (show_activity)
-               printf("Name                   Objects      Alloc       Free   %%Fast Fallb O CmpX   UL\n");
-       else
-               printf("Name                   Objects Objsize    Space "
-                       "Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
-}
-
-/*
- * Find the shortest alias of a slab
- */
-static struct aliasinfo *find_one_alias(struct slabinfo *find)
-{
-       struct aliasinfo *a;
-       struct aliasinfo *best = NULL;
-
-       for(a = aliasinfo;a < aliasinfo + aliases; a++) {
-               if (a->slab == find &&
-                       (!best || strlen(best->name) < strlen(a->name))) {
-                               best = a;
-                               if (strncmp(a->name,"kmall", 5) == 0)
-                                       return best;
-                       }
-       }
-       return best;
-}
-
-static unsigned long slab_size(struct slabinfo *s)
-{
-       return  s->slabs * (page_size << s->order);
-}
-
-static unsigned long slab_activity(struct slabinfo *s)
-{
-       return  s->alloc_fastpath + s->free_fastpath +
-               s->alloc_slowpath + s->free_slowpath;
-}
-
-static void slab_numa(struct slabinfo *s, int mode)
-{
-       int node;
-
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       if (!highest_node) {
-               printf("\n%s: No NUMA information available.\n", s->name);
-               return;
-       }
-
-       if (skip_zero && !s->slabs)
-               return;
-
-       if (!line) {
-               printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
-               for(node = 0; node <= highest_node; node++)
-                       printf(" %4d", node);
-               printf("\n----------------------");
-               for(node = 0; node <= highest_node; node++)
-                       printf("-----");
-               printf("\n");
-       }
-       printf("%-21s ", mode ? "All slabs" : s->name);
-       for(node = 0; node <= highest_node; node++) {
-               char b[20];
-
-               store_size(b, s->numa[node]);
-               printf(" %4s", b);
-       }
-       printf("\n");
-       if (mode) {
-               printf("%-21s ", "Partial slabs");
-               for(node = 0; node <= highest_node; node++) {
-                       char b[20];
-
-                       store_size(b, s->numa_partial[node]);
-                       printf(" %4s", b);
-               }
-               printf("\n");
-       }
-       line++;
-}
-
-static void show_tracking(struct slabinfo *s)
-{
-       printf("\n%s: Kernel object allocation\n", s->name);
-       printf("-----------------------------------------------------------------------\n");
-       if (read_slab_obj(s, "alloc_calls"))
-               printf("%s", buffer);
-       else
-               printf("No Data\n");
-
-       printf("\n%s: Kernel object freeing\n", s->name);
-       printf("------------------------------------------------------------------------\n");
-       if (read_slab_obj(s, "free_calls"))
-               printf("%s", buffer);
-       else
-               printf("No Data\n");
-
-}
-
-static void ops(struct slabinfo *s)
-{
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       if (read_slab_obj(s, "ops")) {
-               printf("\n%s: kmem_cache operations\n", s->name);
-               printf("--------------------------------------------\n");
-               printf("%s", buffer);
-       } else
-               printf("\n%s has no kmem_cache operations\n", s->name);
-}
-
-static const char *onoff(int x)
-{
-       if (x)
-               return "On ";
-       return "Off";
-}
-
-static void slab_stats(struct slabinfo *s)
-{
-       unsigned long total_alloc;
-       unsigned long total_free;
-       unsigned long total;
-
-       if (!s->alloc_slab)
-               return;
-
-       total_alloc = s->alloc_fastpath + s->alloc_slowpath;
-       total_free = s->free_fastpath + s->free_slowpath;
-
-       if (!total_alloc)
-               return;
-
-       printf("\n");
-       printf("Slab Perf Counter       Alloc     Free %%Al %%Fr\n");
-       printf("--------------------------------------------------\n");
-       printf("Fastpath             %8lu %8lu %3lu %3lu\n",
-               s->alloc_fastpath, s->free_fastpath,
-               s->alloc_fastpath * 100 / total_alloc,
-               s->free_fastpath * 100 / total_free);
-       printf("Slowpath             %8lu %8lu %3lu %3lu\n",
-               total_alloc - s->alloc_fastpath, s->free_slowpath,
-               (total_alloc - s->alloc_fastpath) * 100 / total_alloc,
-               s->free_slowpath * 100 / total_free);
-       printf("Page Alloc           %8lu %8lu %3lu %3lu\n",
-               s->alloc_slab, s->free_slab,
-               s->alloc_slab * 100 / total_alloc,
-               s->free_slab * 100 / total_free);
-       printf("Add partial          %8lu %8lu %3lu %3lu\n",
-               s->deactivate_to_head + s->deactivate_to_tail,
-               s->free_add_partial,
-               (s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc,
-               s->free_add_partial * 100 / total_free);
-       printf("Remove partial       %8lu %8lu %3lu %3lu\n",
-               s->alloc_from_partial, s->free_remove_partial,
-               s->alloc_from_partial * 100 / total_alloc,
-               s->free_remove_partial * 100 / total_free);
-
-       printf("Cpu partial list     %8lu %8lu %3lu %3lu\n",
-               s->cpu_partial_alloc, s->cpu_partial_free,
-               s->cpu_partial_alloc * 100 / total_alloc,
-               s->cpu_partial_free * 100 / total_free);
-
-       printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
-               s->deactivate_remote_frees, s->free_frozen,
-               s->deactivate_remote_frees * 100 / total_alloc,
-               s->free_frozen * 100 / total_free);
-
-       printf("Total                %8lu %8lu\n\n", total_alloc, total_free);
-
-       if (s->cpuslab_flush)
-               printf("Flushes %8lu\n", s->cpuslab_flush);
-
-       total = s->deactivate_full + s->deactivate_empty +
-                       s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
-
-       if (total) {
-               printf("\nSlab Deactivation             Ocurrences  %%\n");
-               printf("-------------------------------------------------\n");
-               printf("Slab full                     %7lu  %3lu%%\n",
-                       s->deactivate_full, (s->deactivate_full * 100) / total);
-               printf("Slab empty                    %7lu  %3lu%%\n",
-                       s->deactivate_empty, (s->deactivate_empty * 100) / total);
-               printf("Moved to head of partial list %7lu  %3lu%%\n",
-                       s->deactivate_to_head, (s->deactivate_to_head * 100) / total);
-               printf("Moved to tail of partial list %7lu  %3lu%%\n",
-                       s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
-               printf("Deactivation bypass           %7lu  %3lu%%\n",
-                       s->deactivate_bypass, (s->deactivate_bypass * 100) / total);
-               printf("Refilled from foreign frees   %7lu  %3lu%%\n",
-                       s->alloc_refill, (s->alloc_refill * 100) / total);
-               printf("Node mismatch                 %7lu  %3lu%%\n",
-                       s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
-       }
-
-       if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail)
-               printf("\nCmpxchg_double Looping\n------------------------\n");
-               printf("Locked Cmpxchg Double redos   %lu\nUnlocked Cmpxchg Double redos %lu\n",
-                       s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
-}
-
-static void report(struct slabinfo *s)
-{
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       printf("\nSlabcache: %-20s  Aliases: %2d Order : %2d Objects: %lu\n",
-               s->name, s->aliases, s->order, s->objects);
-       if (s->hwcache_align)
-               printf("** Hardware cacheline aligned\n");
-       if (s->cache_dma)
-               printf("** Memory is allocated in a special DMA zone\n");
-       if (s->destroy_by_rcu)
-               printf("** Slabs are destroyed via RCU\n");
-       if (s->reclaim_account)
-               printf("** Reclaim accounting active\n");
-
-       printf("\nSizes (bytes)     Slabs              Debug                Memory\n");
-       printf("------------------------------------------------------------------------\n");
-       printf("Object : %7d  Total  : %7ld   Sanity Checks : %s  Total: %7ld\n",
-                       s->object_size, s->slabs, onoff(s->sanity_checks),
-                       s->slabs * (page_size << s->order));
-       printf("SlabObj: %7d  Full   : %7ld   Redzoning     : %s  Used : %7ld\n",
-                       s->slab_size, s->slabs - s->partial - s->cpu_slabs,
-                       onoff(s->red_zone), s->objects * s->object_size);
-       printf("SlabSiz: %7d  Partial: %7ld   Poisoning     : %s  Loss : %7ld\n",
-                       page_size << s->order, s->partial, onoff(s->poison),
-                       s->slabs * (page_size << s->order) - s->objects * s->object_size);
-       printf("Loss   : %7d  CpuSlab: %7d   Tracking      : %s  Lalig: %7ld\n",
-                       s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
-                       (s->slab_size - s->object_size) * s->objects);
-       printf("Align  : %7d  Objects: %7d   Tracing       : %s  Lpadd: %7ld\n",
-                       s->align, s->objs_per_slab, onoff(s->trace),
-                       ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
-                       s->slabs);
-
-       ops(s);
-       show_tracking(s);
-       slab_numa(s, 1);
-       slab_stats(s);
-}
-
-static void slabcache(struct slabinfo *s)
-{
-       char size_str[20];
-       char dist_str[40];
-       char flags[20];
-       char *p = flags;
-
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       if (actual_slabs == 1) {
-               report(s);
-               return;
-       }
-
-       if (skip_zero && !show_empty && !s->slabs)
-               return;
-
-       if (show_empty && s->slabs)
-               return;
-
-       store_size(size_str, slab_size(s));
-       snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs,
-                                               s->partial, s->cpu_slabs);
-
-       if (!line++)
-               first_line();
-
-       if (s->aliases)
-               *p++ = '*';
-       if (s->cache_dma)
-               *p++ = 'd';
-       if (s->hwcache_align)
-               *p++ = 'A';
-       if (s->poison)
-               *p++ = 'P';
-       if (s->reclaim_account)
-               *p++ = 'a';
-       if (s->red_zone)
-               *p++ = 'Z';
-       if (s->sanity_checks)
-               *p++ = 'F';
-       if (s->store_user)
-               *p++ = 'U';
-       if (s->trace)
-               *p++ = 'T';
-
-       *p = 0;
-       if (show_activity) {
-               unsigned long total_alloc;
-               unsigned long total_free;
-
-               total_alloc = s->alloc_fastpath + s->alloc_slowpath;
-               total_free = s->free_fastpath + s->free_slowpath;
-
-               printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n",
-                       s->name, s->objects,
-                       total_alloc, total_free,
-                       total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
-                       total_free ? (s->free_fastpath * 100 / total_free) : 0,
-                       s->order_fallback, s->order, s->cmpxchg_double_fail,
-                       s->cmpxchg_double_cpu_fail);
-       }
-       else
-               printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
-                       s->name, s->objects, s->object_size, size_str, dist_str,
-                       s->objs_per_slab, s->order,
-                       s->slabs ? (s->partial * 100) / s->slabs : 100,
-                       s->slabs ? (s->objects * s->object_size * 100) /
-                               (s->slabs * (page_size << s->order)) : 100,
-                       flags);
-}
-
-/*
- * Analyze debug options. Return false if something is amiss.
- */
-static int debug_opt_scan(char *opt)
-{
-       if (!opt || !opt[0] || strcmp(opt, "-") == 0)
-               return 1;
-
-       if (strcasecmp(opt, "a") == 0) {
-               sanity = 1;
-               poison = 1;
-               redzone = 1;
-               tracking = 1;
-               return 1;
-       }
-
-       for ( ; *opt; opt++)
-               switch (*opt) {
-               case 'F' : case 'f':
-                       if (sanity)
-                               return 0;
-                       sanity = 1;
-                       break;
-               case 'P' : case 'p':
-                       if (poison)
-                               return 0;
-                       poison = 1;
-                       break;
-
-               case 'Z' : case 'z':
-                       if (redzone)
-                               return 0;
-                       redzone = 1;
-                       break;
-
-               case 'U' : case 'u':
-                       if (tracking)
-                               return 0;
-                       tracking = 1;
-                       break;
-
-               case 'T' : case 't':
-                       if (tracing)
-                               return 0;
-                       tracing = 1;
-                       break;
-               default:
-                       return 0;
-               }
-       return 1;
-}
-
-static int slab_empty(struct slabinfo *s)
-{
-       if (s->objects > 0)
-               return 0;
-
-       /*
-        * We may still have slabs even if there are no objects. Shrinking will
-        * remove them.
-        */
-       if (s->slabs != 0)
-               set_obj(s, "shrink", 1);
-
-       return 1;
-}
-
-static void slab_debug(struct slabinfo *s)
-{
-       if (strcmp(s->name, "*") == 0)
-               return;
-
-       if (sanity && !s->sanity_checks) {
-               set_obj(s, "sanity", 1);
-       }
-       if (!sanity && s->sanity_checks) {
-               if (slab_empty(s))
-                       set_obj(s, "sanity", 0);
-               else
-                       fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
-       }
-       if (redzone && !s->red_zone) {
-               if (slab_empty(s))
-                       set_obj(s, "red_zone", 1);
-               else
-                       fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
-       }
-       if (!redzone && s->red_zone) {
-               if (slab_empty(s))
-                       set_obj(s, "red_zone", 0);
-               else
-                       fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
-       }
-       if (poison && !s->poison) {
-               if (slab_empty(s))
-                       set_obj(s, "poison", 1);
-               else
-                       fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
-       }
-       if (!poison && s->poison) {
-               if (slab_empty(s))
-                       set_obj(s, "poison", 0);
-               else
-                       fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
-       }
-       if (tracking && !s->store_user) {
-               if (slab_empty(s))
-                       set_obj(s, "store_user", 1);
-               else
-                       fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
-       }
-       if (!tracking && s->store_user) {
-               if (slab_empty(s))
-                       set_obj(s, "store_user", 0);
-               else
-                       fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
-       }
-       if (tracing && !s->trace) {
-               if (slabs == 1)
-                       set_obj(s, "trace", 1);
-               else
-                       fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
-       }
-       if (!tracing && s->trace)
-               set_obj(s, "trace", 1);
-}
-
-static void totals(void)
-{
-       struct slabinfo *s;
-
-       int used_slabs = 0;
-       char b1[20], b2[20], b3[20], b4[20];
-       unsigned long long max = 1ULL << 63;
-
-       /* Object size */
-       unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
-
-       /* Number of partial slabs in a slabcache */
-       unsigned long long min_partial = max, max_partial = 0,
-                               avg_partial, total_partial = 0;
-
-       /* Number of slabs in a slab cache */
-       unsigned long long min_slabs = max, max_slabs = 0,
-                               avg_slabs, total_slabs = 0;
-
-       /* Size of the whole slab */
-       unsigned long long min_size = max, max_size = 0,
-                               avg_size, total_size = 0;
-
-       /* Bytes used for object storage in a slab */
-       unsigned long long min_used = max, max_used = 0,
-                               avg_used, total_used = 0;
-
-       /* Waste: Bytes used for alignment and padding */
-       unsigned long long min_waste = max, max_waste = 0,
-                               avg_waste, total_waste = 0;
-       /* Number of objects in a slab */
-       unsigned long long min_objects = max, max_objects = 0,
-                               avg_objects, total_objects = 0;
-       /* Waste per object */
-       unsigned long long min_objwaste = max,
-                               max_objwaste = 0, avg_objwaste,
-                               total_objwaste = 0;
-
-       /* Memory per object */
-       unsigned long long min_memobj = max,
-                               max_memobj = 0, avg_memobj,
-                               total_objsize = 0;
-
-       /* Percentage of partial slabs per slab */
-       unsigned long min_ppart = 100, max_ppart = 0,
-                               avg_ppart, total_ppart = 0;
-
-       /* Number of objects in partial slabs */
-       unsigned long min_partobj = max, max_partobj = 0,
-                               avg_partobj, total_partobj = 0;
-
-       /* Percentage of partial objects of all objects in a slab */
-       unsigned long min_ppartobj = 100, max_ppartobj = 0,
-                               avg_ppartobj, total_ppartobj = 0;
-
-
-       for (s = slabinfo; s < slabinfo + slabs; s++) {
-               unsigned long long size;
-               unsigned long used;
-               unsigned long long wasted;
-               unsigned long long objwaste;
-               unsigned long percentage_partial_slabs;
-               unsigned long percentage_partial_objs;
-
-               if (!s->slabs || !s->objects)
-                       continue;
-
-               used_slabs++;
-
-               size = slab_size(s);
-               used = s->objects * s->object_size;
-               wasted = size - used;
-               objwaste = s->slab_size - s->object_size;
-
-               percentage_partial_slabs = s->partial * 100 / s->slabs;
-               if (percentage_partial_slabs > 100)
-                       percentage_partial_slabs = 100;
-
-               percentage_partial_objs = s->objects_partial * 100
-                                                       / s->objects;
-
-               if (percentage_partial_objs > 100)
-                       percentage_partial_objs = 100;
-
-               if (s->object_size < min_objsize)
-                       min_objsize = s->object_size;
-               if (s->partial < min_partial)
-                       min_partial = s->partial;
-               if (s->slabs < min_slabs)
-                       min_slabs = s->slabs;
-               if (size < min_size)
-                       min_size = size;
-               if (wasted < min_waste)
-                       min_waste = wasted;
-               if (objwaste < min_objwaste)
-                       min_objwaste = objwaste;
-               if (s->objects < min_objects)
-                       min_objects = s->objects;
-               if (used < min_used)
-                       min_used = used;
-               if (s->objects_partial < min_partobj)
-                       min_partobj = s->objects_partial;
-               if (percentage_partial_slabs < min_ppart)
-                       min_ppart = percentage_partial_slabs;
-               if (percentage_partial_objs < min_ppartobj)
-                       min_ppartobj = percentage_partial_objs;
-               if (s->slab_size < min_memobj)
-                       min_memobj = s->slab_size;
-
-               if (s->object_size > max_objsize)
-                       max_objsize = s->object_size;
-               if (s->partial > max_partial)
-                       max_partial = s->partial;
-               if (s->slabs > max_slabs)
-                       max_slabs = s->slabs;
-               if (size > max_size)
-                       max_size = size;
-               if (wasted > max_waste)
-                       max_waste = wasted;
-               if (objwaste > max_objwaste)
-                       max_objwaste = objwaste;
-               if (s->objects > max_objects)
-                       max_objects = s->objects;
-               if (used > max_used)
-                       max_used = used;
-               if (s->objects_partial > max_partobj)
-                       max_partobj = s->objects_partial;
-               if (percentage_partial_slabs > max_ppart)
-                       max_ppart = percentage_partial_slabs;
-               if (percentage_partial_objs > max_ppartobj)
-                       max_ppartobj = percentage_partial_objs;
-               if (s->slab_size > max_memobj)
-                       max_memobj = s->slab_size;
-
-               total_partial += s->partial;
-               total_slabs += s->slabs;
-               total_size += size;
-               total_waste += wasted;
-
-               total_objects += s->objects;
-               total_used += used;
-               total_partobj += s->objects_partial;
-               total_ppart += percentage_partial_slabs;
-               total_ppartobj += percentage_partial_objs;
-
-               total_objwaste += s->objects * objwaste;
-               total_objsize += s->objects * s->slab_size;
-       }
-
-       if (!total_objects) {
-               printf("No objects\n");
-               return;
-       }
-       if (!used_slabs) {
-               printf("No slabs\n");
-               return;
-       }
-
-       /* Per slab averages */
-       avg_partial = total_partial / used_slabs;
-       avg_slabs = total_slabs / used_slabs;
-       avg_size = total_size / used_slabs;
-       avg_waste = total_waste / used_slabs;
-
-       avg_objects = total_objects / used_slabs;
-       avg_used = total_used / used_slabs;
-       avg_partobj = total_partobj / used_slabs;
-       avg_ppart = total_ppart / used_slabs;
-       avg_ppartobj = total_ppartobj / used_slabs;
-
-       /* Per object object sizes */
-       avg_objsize = total_used / total_objects;
-       avg_objwaste = total_objwaste / total_objects;
-       avg_partobj = total_partobj * 100 / total_objects;
-       avg_memobj = total_objsize / total_objects;
-
-       printf("Slabcache Totals\n");
-       printf("----------------\n");
-       printf("Slabcaches : %3d      Aliases  : %3d->%-3d Active: %3d\n",
-                       slabs, aliases, alias_targets, used_slabs);
-
-       store_size(b1, total_size);store_size(b2, total_waste);
-       store_size(b3, total_waste * 100 / total_used);
-       printf("Memory used: %6s   # Loss   : %6s   MRatio:%6s%%\n", b1, b2, b3);
-
-       store_size(b1, total_objects);store_size(b2, total_partobj);
-       store_size(b3, total_partobj * 100 / total_objects);
-       printf("# Objects  : %6s   # PartObj: %6s   ORatio:%6s%%\n", b1, b2, b3);
-
-       printf("\n");
-       printf("Per Cache    Average         Min         Max       Total\n");
-       printf("---------------------------------------------------------\n");
-
-       store_size(b1, avg_objects);store_size(b2, min_objects);
-       store_size(b3, max_objects);store_size(b4, total_objects);
-       printf("#Objects  %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_slabs);store_size(b2, min_slabs);
-       store_size(b3, max_slabs);store_size(b4, total_slabs);
-       printf("#Slabs    %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_partial);store_size(b2, min_partial);
-       store_size(b3, max_partial);store_size(b4, total_partial);
-       printf("#PartSlab %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-       store_size(b1, avg_ppart);store_size(b2, min_ppart);
-       store_size(b3, max_ppart);
-       store_size(b4, total_partial * 100  / total_slabs);
-       printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_partobj);store_size(b2, min_partobj);
-       store_size(b3, max_partobj);
-       store_size(b4, total_partobj);
-       printf("PartObjs  %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
-       store_size(b3, max_ppartobj);
-       store_size(b4, total_partobj * 100 / total_objects);
-       printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_size);store_size(b2, min_size);
-       store_size(b3, max_size);store_size(b4, total_size);
-       printf("Memory    %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_used);store_size(b2, min_used);
-       store_size(b3, max_used);store_size(b4, total_used);
-       printf("Used      %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-
-       store_size(b1, avg_waste);store_size(b2, min_waste);
-       store_size(b3, max_waste);store_size(b4, total_waste);
-       printf("Loss      %10s  %10s  %10s  %10s\n",
-                       b1,     b2,     b3,     b4);
-
-       printf("\n");
-       printf("Per Object   Average         Min         Max\n");
-       printf("---------------------------------------------\n");
-
-       store_size(b1, avg_memobj);store_size(b2, min_memobj);
-       store_size(b3, max_memobj);
-       printf("Memory    %10s  %10s  %10s\n",
-                       b1,     b2,     b3);
-       store_size(b1, avg_objsize);store_size(b2, min_objsize);
-       store_size(b3, max_objsize);
-       printf("User      %10s  %10s  %10s\n",
-                       b1,     b2,     b3);
-
-       store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
-       store_size(b3, max_objwaste);
-       printf("Loss      %10s  %10s  %10s\n",
-                       b1,     b2,     b3);
-}
-
-static void sort_slabs(void)
-{
-       struct slabinfo *s1,*s2;
-
-       for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
-               for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
-                       int result;
-
-                       if (sort_size)
-                               result = slab_size(s1) < slab_size(s2);
-                       else if (sort_active)
-                               result = slab_activity(s1) < slab_activity(s2);
-                       else
-                               result = strcasecmp(s1->name, s2->name);
-
-                       if (show_inverted)
-                               result = -result;
-
-                       if (result > 0) {
-                               struct slabinfo t;
-
-                               memcpy(&t, s1, sizeof(struct slabinfo));
-                               memcpy(s1, s2, sizeof(struct slabinfo));
-                               memcpy(s2, &t, sizeof(struct slabinfo));
-                       }
-               }
-       }
-}
-
-static void sort_aliases(void)
-{
-       struct aliasinfo *a1,*a2;
-
-       for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
-               for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
-                       char *n1, *n2;
-
-                       n1 = a1->name;
-                       n2 = a2->name;
-                       if (show_alias && !show_inverted) {
-                               n1 = a1->ref;
-                               n2 = a2->ref;
-                       }
-                       if (strcasecmp(n1, n2) > 0) {
-                               struct aliasinfo t;
-
-                               memcpy(&t, a1, sizeof(struct aliasinfo));
-                               memcpy(a1, a2, sizeof(struct aliasinfo));
-                               memcpy(a2, &t, sizeof(struct aliasinfo));
-                       }
-               }
-       }
-}
-
-static void link_slabs(void)
-{
-       struct aliasinfo *a;
-       struct slabinfo *s;
-
-       for (a = aliasinfo; a < aliasinfo + aliases; a++) {
-
-               for (s = slabinfo; s < slabinfo + slabs; s++)
-                       if (strcmp(a->ref, s->name) == 0) {
-                               a->slab = s;
-                               s->refs++;
-                               break;
-                       }
-               if (s == slabinfo + slabs)
-                       fatal("Unresolved alias %s\n", a->ref);
-       }
-}
-
-static void alias(void)
-{
-       struct aliasinfo *a;
-       char *active = NULL;
-
-       sort_aliases();
-       link_slabs();
-
-       for(a = aliasinfo; a < aliasinfo + aliases; a++) {
-
-               if (!show_single_ref && a->slab->refs == 1)
-                       continue;
-
-               if (!show_inverted) {
-                       if (active) {
-                               if (strcmp(a->slab->name, active) == 0) {
-                                       printf(" %s", a->name);
-                                       continue;
-                               }
-                       }
-                       printf("\n%-12s <- %s", a->slab->name, a->name);
-                       active = a->slab->name;
-               }
-               else
-                       printf("%-20s -> %s\n", a->name, a->slab->name);
-       }
-       if (active)
-               printf("\n");
-}
-
-
-static void rename_slabs(void)
-{
-       struct slabinfo *s;
-       struct aliasinfo *a;
-
-       for (s = slabinfo; s < slabinfo + slabs; s++) {
-               if (*s->name != ':')
-                       continue;
-
-               if (s->refs > 1 && !show_first_alias)
-                       continue;
-
-               a = find_one_alias(s);
-
-               if (a)
-                       s->name = a->name;
-               else {
-                       s->name = "*";
-                       actual_slabs--;
-               }
-       }
-}
-
-static int slab_mismatch(char *slab)
-{
-       return regexec(&pattern, slab, 0, NULL, 0);
-}
-
-static void read_slab_dir(void)
-{
-       DIR *dir;
-       struct dirent *de;
-       struct slabinfo *slab = slabinfo;
-       struct aliasinfo *alias = aliasinfo;
-       char *p;
-       char *t;
-       int count;
-
-       if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
-               fatal("SYSFS support for SLUB not active\n");
-
-       dir = opendir(".");
-       while ((de = readdir(dir))) {
-               if (de->d_name[0] == '.' ||
-                       (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
-                               continue;
-               switch (de->d_type) {
-                  case DT_LNK:
-                       alias->name = strdup(de->d_name);
-                       count = readlink(de->d_name, buffer, sizeof(buffer)-1);
-
-                       if (count < 0)
-                               fatal("Cannot read symlink %s\n", de->d_name);
-
-                       buffer[count] = 0;
-                       p = buffer + count;
-                       while (p > buffer && p[-1] != '/')
-                               p--;
-                       alias->ref = strdup(p);
-                       alias++;
-                       break;
-                  case DT_DIR:
-                       if (chdir(de->d_name))
-                               fatal("Unable to access slab %s\n", slab->name);
-                       slab->name = strdup(de->d_name);
-                       slab->alias = 0;
-                       slab->refs = 0;
-                       slab->aliases = get_obj("aliases");
-                       slab->align = get_obj("align");
-                       slab->cache_dma = get_obj("cache_dma");
-                       slab->cpu_slabs = get_obj("cpu_slabs");
-                       slab->destroy_by_rcu = get_obj("destroy_by_rcu");
-                       slab->hwcache_align = get_obj("hwcache_align");
-                       slab->object_size = get_obj("object_size");
-                       slab->objects = get_obj("objects");
-                       slab->objects_partial = get_obj("objects_partial");
-                       slab->objects_total = get_obj("objects_total");
-                       slab->objs_per_slab = get_obj("objs_per_slab");
-                       slab->order = get_obj("order");
-                       slab->partial = get_obj("partial");
-                       slab->partial = get_obj_and_str("partial", &t);
-                       decode_numa_list(slab->numa_partial, t);
-                       free(t);
-                       slab->poison = get_obj("poison");
-                       slab->reclaim_account = get_obj("reclaim_account");
-                       slab->red_zone = get_obj("red_zone");
-                       slab->sanity_checks = get_obj("sanity_checks");
-                       slab->slab_size = get_obj("slab_size");
-                       slab->slabs = get_obj_and_str("slabs", &t);
-                       decode_numa_list(slab->numa, t);
-                       free(t);
-                       slab->store_user = get_obj("store_user");
-                       slab->trace = get_obj("trace");
-                       slab->alloc_fastpath = get_obj("alloc_fastpath");
-                       slab->alloc_slowpath = get_obj("alloc_slowpath");
-                       slab->free_fastpath = get_obj("free_fastpath");
-                       slab->free_slowpath = get_obj("free_slowpath");
-                       slab->free_frozen= get_obj("free_frozen");
-                       slab->free_add_partial = get_obj("free_add_partial");
-                       slab->free_remove_partial = get_obj("free_remove_partial");
-                       slab->alloc_from_partial = get_obj("alloc_from_partial");
-                       slab->alloc_slab = get_obj("alloc_slab");
-                       slab->alloc_refill = get_obj("alloc_refill");
-                       slab->free_slab = get_obj("free_slab");
-                       slab->cpuslab_flush = get_obj("cpuslab_flush");
-                       slab->deactivate_full = get_obj("deactivate_full");
-                       slab->deactivate_empty = get_obj("deactivate_empty");
-                       slab->deactivate_to_head = get_obj("deactivate_to_head");
-                       slab->deactivate_to_tail = get_obj("deactivate_to_tail");
-                       slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
-                       slab->order_fallback = get_obj("order_fallback");
-                       slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
-                       slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
-                       slab->cpu_partial_alloc = get_obj("cpu_partial_alloc");
-                       slab->cpu_partial_free = get_obj("cpu_partial_free");
-                       slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
-                       slab->deactivate_bypass = get_obj("deactivate_bypass");
-                       chdir("..");
-                       if (slab->name[0] == ':')
-                               alias_targets++;
-                       slab++;
-                       break;
-                  default :
-                       fatal("Unknown file type %lx\n", de->d_type);
-               }
-       }
-       closedir(dir);
-       slabs = slab - slabinfo;
-       actual_slabs = slabs;
-       aliases = alias - aliasinfo;
-       if (slabs > MAX_SLABS)
-               fatal("Too many slabs\n");
-       if (aliases > MAX_ALIASES)
-               fatal("Too many aliases\n");
-}
-
-static void output_slabs(void)
-{
-       struct slabinfo *slab;
-
-       for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
-
-               if (slab->alias)
-                       continue;
-
-
-               if (show_numa)
-                       slab_numa(slab, 0);
-               else if (show_track)
-                       show_tracking(slab);
-               else if (validate)
-                       slab_validate(slab);
-               else if (shrink)
-                       slab_shrink(slab);
-               else if (set_debug)
-                       slab_debug(slab);
-               else if (show_ops)
-                       ops(slab);
-               else if (show_slab)
-                       slabcache(slab);
-               else if (show_report)
-                       report(slab);
-       }
-}
-
-struct option opts[] = {
-       { "aliases", 0, NULL, 'a' },
-       { "activity", 0, NULL, 'A' },
-       { "debug", 2, NULL, 'd' },
-       { "display-activity", 0, NULL, 'D' },
-       { "empty", 0, NULL, 'e' },
-       { "first-alias", 0, NULL, 'f' },
-       { "help", 0, NULL, 'h' },
-       { "inverted", 0, NULL, 'i'},
-       { "numa", 0, NULL, 'n' },
-       { "ops", 0, NULL, 'o' },
-       { "report", 0, NULL, 'r' },
-       { "shrink", 0, NULL, 's' },
-       { "slabs", 0, NULL, 'l' },
-       { "track", 0, NULL, 't'},
-       { "validate", 0, NULL, 'v' },
-       { "zero", 0, NULL, 'z' },
-       { "1ref", 0, NULL, '1'},
-       { NULL, 0, NULL, 0 }
-};
-
-int main(int argc, char *argv[])
-{
-       int c;
-       int err;
-       char *pattern_source;
-
-       page_size = getpagesize();
-
-       while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTS",
-                                               opts, NULL)) != -1)
-               switch (c) {
-               case '1':
-                       show_single_ref = 1;
-                       break;
-               case 'a':
-                       show_alias = 1;
-                       break;
-               case 'A':
-                       sort_active = 1;
-                       break;
-               case 'd':
-                       set_debug = 1;
-                       if (!debug_opt_scan(optarg))
-                               fatal("Invalid debug option '%s'\n", optarg);
-                       break;
-               case 'D':
-                       show_activity = 1;
-                       break;
-               case 'e':
-                       show_empty = 1;
-                       break;
-               case 'f':
-                       show_first_alias = 1;
-                       break;
-               case 'h':
-                       usage();
-                       return 0;
-               case 'i':
-                       show_inverted = 1;
-                       break;
-               case 'n':
-                       show_numa = 1;
-                       break;
-               case 'o':
-                       show_ops = 1;
-                       break;
-               case 'r':
-                       show_report = 1;
-                       break;
-               case 's':
-                       shrink = 1;
-                       break;
-               case 'l':
-                       show_slab = 1;
-                       break;
-               case 't':
-                       show_track = 1;
-                       break;
-               case 'v':
-                       validate = 1;
-                       break;
-               case 'z':
-                       skip_zero = 0;
-                       break;
-               case 'T':
-                       show_totals = 1;
-                       break;
-               case 'S':
-                       sort_size = 1;
-                       break;
-
-               default:
-                       fatal("%s: Invalid option '%c'\n", argv[0], optopt);
-
-       }
-
-       if (!show_slab && !show_alias && !show_track && !show_report
-               && !validate && !shrink && !set_debug && !show_ops)
-                       show_slab = 1;
-
-       if (argc > optind)
-               pattern_source = argv[optind];
-       else
-               pattern_source = ".*";
-
-       err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
-       if (err)
-               fatal("%s: Invalid pattern '%s' code %d\n",
-                       argv[0], pattern_source, err);
-       read_slab_dir();
-       if (show_alias)
-               alias();
-       else
-       if (show_totals)
-               totals();
-       else {
-               link_slabs();
-               rename_slabs();
-               sort_slabs();
-               output_slabs();
-       }
-       return 0;
-}
index 4ec84018cc1364f8f905ee30c31e52f04d7ec6ff..28bc57ee757cf04d7b2166dc3e4b236b5fd19de6 100644 (file)
@@ -1,10 +1,15 @@
-TARGETS = breakpoints
+TARGETS = breakpoints vm
 
 all:
        for TARGET in $(TARGETS); do \
                make -C $$TARGET; \
        done;
 
+run_tests: all
+       for TARGET in $(TARGETS); do \
+               make -C $$TARGET run_tests; \
+       done;
+
 clean:
        for TARGET in $(TARGETS); do \
                make -C $$TARGET clean; \
index f362722cdce7e564ad70d9d1c6df1ae094f0e2f7..931278035f5c94746fbe3ea5376fccdcf81e5747 100644 (file)
@@ -11,10 +11,13 @@ endif
 
 all:
 ifeq ($(ARCH),x86)
-       gcc breakpoint_test.c -o run_test
+       gcc breakpoint_test.c -o breakpoint_test
 else
        echo "Not an x86 target, can't build breakpoints selftests"
 endif
 
+run_tests:
+       ./breakpoint_test
+
 clean:
-       rm -fr run_test
+       rm -fr breakpoint_test
diff --git a/tools/testing/selftests/run_tests b/tools/testing/selftests/run_tests
deleted file mode 100644 (file)
index 320718a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-TARGETS=breakpoints
-
-for TARGET in $TARGETS
-do
-       $TARGET/run_test
-done
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
new file mode 100644 (file)
index 0000000..b336b24
--- /dev/null
@@ -0,0 +1,14 @@
+# Makefile for vm selftests
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall -Wextra
+
+all: hugepage-mmap hugepage-shm  map_hugetlb
+%: %.c
+       $(CC) $(CFLAGS) -o $@ $^
+
+run_tests: all
+       /bin/sh ./run_vmtests
+
+clean:
+       $(RM) hugepage-mmap hugepage-shm  map_hugetlb
diff --git a/tools/testing/selftests/vm/hugepage-mmap.c b/tools/testing/selftests/vm/hugepage-mmap.c
new file mode 100644 (file)
index 0000000..a10f310
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * hugepage-mmap:
+ *
+ * Example of using huge page memory in a user application using the mmap
+ * system call.  Before running this application, make sure that the
+ * administrator has mounted the hugetlbfs filesystem (on some directory
+ * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
+ * example, the app is requesting memory of size 256MB that is backed by
+ * huge pages.
+ *
+ * For the ia64 architecture, the Linux kernel reserves Region number 4 for
+ * huge pages.  That means that if one requires a fixed address, a huge page
+ * aligned address starting with 0x800000... will be required.  If a fixed
+ * address is not required, the kernel will select an address in the proper
+ * range.
+ * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#define FILE_NAME "huge/hugepagefile"
+#define LENGTH (256UL*1024*1024)
+#define PROTECTION (PROT_READ | PROT_WRITE)
+
+/* Only ia64 requires this */
+#ifdef __ia64__
+#define ADDR (void *)(0x8000000000000000UL)
+#define FLAGS (MAP_SHARED | MAP_FIXED)
+#else
+#define ADDR (void *)(0x0UL)
+#define FLAGS (MAP_SHARED)
+#endif
+
+static void check_bytes(char *addr)
+{
+       printf("First hex is %x\n", *((unsigned int *)addr));
+}
+
+static void write_bytes(char *addr)
+{
+       unsigned long i;
+
+       for (i = 0; i < LENGTH; i++)
+               *(addr + i) = (char)i;
+}
+
+static int read_bytes(char *addr)
+{
+       unsigned long i;
+
+       check_bytes(addr);
+       for (i = 0; i < LENGTH; i++)
+               if (*(addr + i) != (char)i) {
+                       printf("Mismatch at %lu\n", i);
+                       return 1;
+               }
+       return 0;
+}
+
+int main(void)
+{
+       void *addr;
+       int fd, ret;
+
+       fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
+       if (fd < 0) {
+               perror("Open failed");
+               exit(1);
+       }
+
+       addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
+       if (addr == MAP_FAILED) {
+               perror("mmap");
+               unlink(FILE_NAME);
+               exit(1);
+       }
+
+       printf("Returned address is %p\n", addr);
+       check_bytes(addr);
+       write_bytes(addr);
+       ret = read_bytes(addr);
+
+       munmap(addr, LENGTH);
+       close(fd);
+       unlink(FILE_NAME);
+
+       return ret;
+}
diff --git a/tools/testing/selftests/vm/hugepage-shm.c b/tools/testing/selftests/vm/hugepage-shm.c
new file mode 100644 (file)
index 0000000..0d0ef4f
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * hugepage-shm:
+ *
+ * Example of using huge page memory in a user application using Sys V shared
+ * memory system calls.  In this example the app is requesting 256MB of
+ * memory that is backed by huge pages.  The application uses the flag
+ * SHM_HUGETLB in the shmget system call to inform the kernel that it is
+ * requesting huge pages.
+ *
+ * For the ia64 architecture, the Linux kernel reserves Region number 4 for
+ * huge pages.  That means that if one requires a fixed address, a huge page
+ * aligned address starting with 0x800000... will be required.  If a fixed
+ * address is not required, the kernel will select an address in the proper
+ * range.
+ * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
+ *
+ * Note: The default shared memory limit is quite low on many kernels,
+ * you may need to increase it via:
+ *
+ * echo 268435456 > /proc/sys/kernel/shmmax
+ *
+ * This will increase the maximum size per shared memory segment to 256MB.
+ * The other limit that you will hit eventually is shmall which is the
+ * total amount of shared memory in pages. To set it to 16GB on a system
+ * with a 4kB pagesize do:
+ *
+ * echo 4194304 > /proc/sys/kernel/shmall
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+
+#ifndef SHM_HUGETLB
+#define SHM_HUGETLB 04000
+#endif
+
+#define LENGTH (256UL*1024*1024)
+
+#define dprintf(x)  printf(x)
+
+/* Only ia64 requires this */
+#ifdef __ia64__
+#define ADDR (void *)(0x8000000000000000UL)
+#define SHMAT_FLAGS (SHM_RND)
+#else
+#define ADDR (void *)(0x0UL)
+#define SHMAT_FLAGS (0)
+#endif
+
+int main(void)
+{
+       int shmid;
+       unsigned long i;
+       char *shmaddr;
+
+       shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
+       if (shmid < 0) {
+               perror("shmget");
+               exit(1);
+       }
+       printf("shmid: 0x%x\n", shmid);
+
+       shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
+       if (shmaddr == (char *)-1) {
+               perror("Shared memory attach failure");
+               shmctl(shmid, IPC_RMID, NULL);
+               exit(2);
+       }
+       printf("shmaddr: %p\n", shmaddr);
+
+       dprintf("Starting the writes:\n");
+       for (i = 0; i < LENGTH; i++) {
+               shmaddr[i] = (char)(i);
+               if (!(i % (1024 * 1024)))
+                       dprintf(".");
+       }
+       dprintf("\n");
+
+       dprintf("Starting the Check...");
+       for (i = 0; i < LENGTH; i++)
+               if (shmaddr[i] != (char)i) {
+                       printf("\nIndex %lu mismatched\n", i);
+                       exit(3);
+               }
+       dprintf("Done.\n");
+
+       if (shmdt((const void *)shmaddr) != 0) {
+               perror("Detach failure");
+               shmctl(shmid, IPC_RMID, NULL);
+               exit(4);
+       }
+
+       shmctl(shmid, IPC_RMID, NULL);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c
new file mode 100644 (file)
index 0000000..ac56639
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Example of using hugepage memory in a user application using the mmap
+ * system call with MAP_HUGETLB flag.  Before running this program make
+ * sure the administrator has allocated enough default sized huge pages
+ * to cover the 256 MB allocation.
+ *
+ * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
+ * That means the addresses starting with 0x800000... will need to be
+ * specified.  Specifying a fixed address is not required on ppc64, i386
+ * or x86_64.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#define LENGTH (256UL*1024*1024)
+#define PROTECTION (PROT_READ | PROT_WRITE)
+
+#ifndef MAP_HUGETLB
+#define MAP_HUGETLB 0x40000 /* arch specific */
+#endif
+
+/* Only ia64 requires this */
+#ifdef __ia64__
+#define ADDR (void *)(0x8000000000000000UL)
+#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED)
+#else
+#define ADDR (void *)(0x0UL)
+#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
+#endif
+
+static void check_bytes(char *addr)
+{
+       printf("First hex is %x\n", *((unsigned int *)addr));
+}
+
+static void write_bytes(char *addr)
+{
+       unsigned long i;
+
+       for (i = 0; i < LENGTH; i++)
+               *(addr + i) = (char)i;
+}
+
+static int read_bytes(char *addr)
+{
+       unsigned long i;
+
+       check_bytes(addr);
+       for (i = 0; i < LENGTH; i++)
+               if (*(addr + i) != (char)i) {
+                       printf("Mismatch at %lu\n", i);
+                       return 1;
+               }
+       return 0;
+}
+
+int main(void)
+{
+       void *addr;
+       int ret;
+
+       addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
+       if (addr == MAP_FAILED) {
+               perror("mmap");
+               exit(1);
+       }
+
+       printf("Returned address is %p\n", addr);
+       check_bytes(addr);
+       write_bytes(addr);
+       ret = read_bytes(addr);
+
+       munmap(addr, LENGTH);
+
+       return ret;
+}
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
new file mode 100644 (file)
index 0000000..8b40bd5
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/bash
+#please run as root
+
+#we need 256M, below is the size in kB
+needmem=262144
+mnt=./huge
+
+#get pagesize and freepages from /proc/meminfo
+while read name size unit; do
+       if [ "$name" = "HugePages_Free:" ]; then
+               freepgs=$size
+       fi
+       if [ "$name" = "Hugepagesize:" ]; then
+               pgsize=$size
+       fi
+done < /proc/meminfo
+
+#set proper nr_hugepages
+if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then
+       nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
+       needpgs=`expr $needmem / $pgsize`
+       if [ $freepgs -lt $needpgs ]; then
+               lackpgs=$(( $needpgs - $freepgs ))
+               echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
+               if [ $? -ne 0 ]; then
+                       echo "Please run this test as root"
+                       exit 1
+               fi
+       fi
+else
+       echo "no hugetlbfs support in kernel?"
+       exit 1
+fi
+
+mkdir $mnt
+mount -t hugetlbfs none $mnt
+
+echo "--------------------"
+echo "runing hugepage-mmap"
+echo "--------------------"
+./hugepage-mmap
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+else
+       echo "[PASS]"
+fi
+
+shmmax=`cat /proc/sys/kernel/shmmax`
+shmall=`cat /proc/sys/kernel/shmall`
+echo 268435456 > /proc/sys/kernel/shmmax
+echo 4194304 > /proc/sys/kernel/shmall
+echo "--------------------"
+echo "runing hugepage-shm"
+echo "--------------------"
+./hugepage-shm
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+else
+       echo "[PASS]"
+fi
+echo $shmmax > /proc/sys/kernel/shmmax
+echo $shmall > /proc/sys/kernel/shmall
+
+echo "--------------------"
+echo "runing map_hugetlb"
+echo "--------------------"
+./map_hugetlb
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+else
+       echo "[PASS]"
+fi
+
+#cleanup
+umount $mnt
+rm -rf $mnt
+echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
new file mode 100644 (file)
index 0000000..8e30e5c
--- /dev/null
@@ -0,0 +1,11 @@
+# Makefile for vm tools
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall -Wextra
+
+all: page-types slabinfo
+%: %.c
+       $(CC) $(CFLAGS) -o $@ $^
+
+clean:
+       $(RM) page-types slabinfo
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
new file mode 100644 (file)
index 0000000..7dab7b2
--- /dev/null
@@ -0,0 +1,1102 @@
+/*
+ * page-types: Tool for querying page flags
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should find a copy of v2 of the GNU General Public License somewhere on
+ * your Linux system; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) 2009 Intel corporation
+ *
+ * Authors: Wu Fengguang <fengguang.wu@intel.com>
+ */
+
+#define _LARGEFILE64_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/mount.h>
+#include <sys/statfs.h>
+#include "../../include/linux/magic.h"
+
+
+#ifndef MAX_PATH
+# define MAX_PATH 256
+#endif
+
+#ifndef STR
+# define _STR(x) #x
+# define STR(x) _STR(x)
+#endif
+
+/*
+ * pagemap kernel ABI bits
+ */
+
+#define PM_ENTRY_BYTES      sizeof(uint64_t)
+#define PM_STATUS_BITS      3
+#define PM_STATUS_OFFSET    (64 - PM_STATUS_BITS)
+#define PM_STATUS_MASK      (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET)
+#define PM_STATUS(nr)       (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK)
+#define PM_PSHIFT_BITS      6
+#define PM_PSHIFT_OFFSET    (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
+#define PM_PSHIFT_MASK      (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
+#define PM_PSHIFT(x)        (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
+#define PM_PFRAME_MASK      ((1LL << PM_PSHIFT_OFFSET) - 1)
+#define PM_PFRAME(x)        ((x) & PM_PFRAME_MASK)
+
+#define PM_PRESENT          PM_STATUS(4LL)
+#define PM_SWAP             PM_STATUS(2LL)
+
+
+/*
+ * kernel page flags
+ */
+
+#define KPF_BYTES              8
+#define PROC_KPAGEFLAGS                "/proc/kpageflags"
+
+/* copied from kpageflags_read() */
+#define KPF_LOCKED             0
+#define KPF_ERROR              1
+#define KPF_REFERENCED         2
+#define KPF_UPTODATE           3
+#define KPF_DIRTY              4
+#define KPF_LRU                        5
+#define KPF_ACTIVE             6
+#define KPF_SLAB               7
+#define KPF_WRITEBACK          8
+#define KPF_RECLAIM            9
+#define KPF_BUDDY              10
+
+/* [11-20] new additions in 2.6.31 */
+#define KPF_MMAP               11
+#define KPF_ANON               12
+#define KPF_SWAPCACHE          13
+#define KPF_SWAPBACKED         14
+#define KPF_COMPOUND_HEAD      15
+#define KPF_COMPOUND_TAIL      16
+#define KPF_HUGE               17
+#define KPF_UNEVICTABLE                18
+#define KPF_HWPOISON           19
+#define KPF_NOPAGE             20
+#define KPF_KSM                        21
+#define KPF_THP                        22
+
+/* [32-] kernel hacking assistances */
+#define KPF_RESERVED           32
+#define KPF_MLOCKED            33
+#define KPF_MAPPEDTODISK       34
+#define KPF_PRIVATE            35
+#define KPF_PRIVATE_2          36
+#define KPF_OWNER_PRIVATE      37
+#define KPF_ARCH               38
+#define KPF_UNCACHED           39
+
+/* [48-] take some arbitrary free slots for expanding overloaded flags
+ * not part of kernel API
+ */
+#define KPF_READAHEAD          48
+#define KPF_SLOB_FREE          49
+#define KPF_SLUB_FROZEN                50
+#define KPF_SLUB_DEBUG         51
+
+#define KPF_ALL_BITS           ((uint64_t)~0ULL)
+#define KPF_HACKERS_BITS       (0xffffULL << 32)
+#define KPF_OVERLOADED_BITS    (0xffffULL << 48)
+#define BIT(name)              (1ULL << KPF_##name)
+#define BITS_COMPOUND          (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL))
+
+static const char * const page_flag_names[] = {
+       [KPF_LOCKED]            = "L:locked",
+       [KPF_ERROR]             = "E:error",
+       [KPF_REFERENCED]        = "R:referenced",
+       [KPF_UPTODATE]          = "U:uptodate",
+       [KPF_DIRTY]             = "D:dirty",
+       [KPF_LRU]               = "l:lru",
+       [KPF_ACTIVE]            = "A:active",
+       [KPF_SLAB]              = "S:slab",
+       [KPF_WRITEBACK]         = "W:writeback",
+       [KPF_RECLAIM]           = "I:reclaim",
+       [KPF_BUDDY]             = "B:buddy",
+
+       [KPF_MMAP]              = "M:mmap",
+       [KPF_ANON]              = "a:anonymous",
+       [KPF_SWAPCACHE]         = "s:swapcache",
+       [KPF_SWAPBACKED]        = "b:swapbacked",
+       [KPF_COMPOUND_HEAD]     = "H:compound_head",
+       [KPF_COMPOUND_TAIL]     = "T:compound_tail",
+       [KPF_HUGE]              = "G:huge",
+       [KPF_UNEVICTABLE]       = "u:unevictable",
+       [KPF_HWPOISON]          = "X:hwpoison",
+       [KPF_NOPAGE]            = "n:nopage",
+       [KPF_KSM]               = "x:ksm",
+       [KPF_THP]               = "t:thp",
+
+       [KPF_RESERVED]          = "r:reserved",
+       [KPF_MLOCKED]           = "m:mlocked",
+       [KPF_MAPPEDTODISK]      = "d:mappedtodisk",
+       [KPF_PRIVATE]           = "P:private",
+       [KPF_PRIVATE_2]         = "p:private_2",
+       [KPF_OWNER_PRIVATE]     = "O:owner_private",
+       [KPF_ARCH]              = "h:arch",
+       [KPF_UNCACHED]          = "c:uncached",
+
+       [KPF_READAHEAD]         = "I:readahead",
+       [KPF_SLOB_FREE]         = "P:slob_free",
+       [KPF_SLUB_FROZEN]       = "A:slub_frozen",
+       [KPF_SLUB_DEBUG]        = "E:slub_debug",
+};
+
+
+static const char * const debugfs_known_mountpoints[] = {
+       "/sys/kernel/debug",
+       "/debug",
+       0,
+};
+
+/*
+ * data structures
+ */
+
+static int             opt_raw;        /* for kernel developers */
+static int             opt_list;       /* list pages (in ranges) */
+static int             opt_no_summary; /* don't show summary */
+static pid_t           opt_pid;        /* process to walk */
+
+#define MAX_ADDR_RANGES        1024
+static int             nr_addr_ranges;
+static unsigned long   opt_offset[MAX_ADDR_RANGES];
+static unsigned long   opt_size[MAX_ADDR_RANGES];
+
+#define MAX_VMAS       10240
+static int             nr_vmas;
+static unsigned long   pg_start[MAX_VMAS];
+static unsigned long   pg_end[MAX_VMAS];
+
+#define MAX_BIT_FILTERS        64
+static int             nr_bit_filters;
+static uint64_t                opt_mask[MAX_BIT_FILTERS];
+static uint64_t                opt_bits[MAX_BIT_FILTERS];
+
+static int             page_size;
+
+static int             pagemap_fd;
+static int             kpageflags_fd;
+
+static int             opt_hwpoison;
+static int             opt_unpoison;
+
+static char            hwpoison_debug_fs[MAX_PATH+1];
+static int             hwpoison_inject_fd;
+static int             hwpoison_forget_fd;
+
+#define HASH_SHIFT     13
+#define HASH_SIZE      (1 << HASH_SHIFT)
+#define HASH_MASK      (HASH_SIZE - 1)
+#define HASH_KEY(flags)        (flags & HASH_MASK)
+
+static unsigned long   total_pages;
+static unsigned long   nr_pages[HASH_SIZE];
+static uint64_t                page_flags[HASH_SIZE];
+
+
+/*
+ * helper functions
+ */
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define min_t(type, x, y) ({                   \
+       type __min1 = (x);                      \
+       type __min2 = (y);                      \
+       __min1 < __min2 ? __min1 : __min2; })
+
+#define max_t(type, x, y) ({                   \
+       type __max1 = (x);                      \
+       type __max2 = (y);                      \
+       __max1 > __max2 ? __max1 : __max2; })
+
+static unsigned long pages2mb(unsigned long pages)
+{
+       return (pages * page_size) >> 20;
+}
+
+static void fatal(const char *x, ...)
+{
+       va_list ap;
+
+       va_start(ap, x);
+       vfprintf(stderr, x, ap);
+       va_end(ap);
+       exit(EXIT_FAILURE);
+}
+
+static int checked_open(const char *pathname, int flags)
+{
+       int fd = open(pathname, flags);
+
+       if (fd < 0) {
+               perror(pathname);
+               exit(EXIT_FAILURE);
+       }
+
+       return fd;
+}
+
+/*
+ * pagemap/kpageflags routines
+ */
+
+static unsigned long do_u64_read(int fd, char *name,
+                                uint64_t *buf,
+                                unsigned long index,
+                                unsigned long count)
+{
+       long bytes;
+
+       if (index > ULONG_MAX / 8)
+               fatal("index overflow: %lu\n", index);
+
+       if (lseek(fd, index * 8, SEEK_SET) < 0) {
+               perror(name);
+               exit(EXIT_FAILURE);
+       }
+
+       bytes = read(fd, buf, count * 8);
+       if (bytes < 0) {
+               perror(name);
+               exit(EXIT_FAILURE);
+       }
+       if (bytes % 8)
+               fatal("partial read: %lu bytes\n", bytes);
+
+       return bytes / 8;
+}
+
+static unsigned long kpageflags_read(uint64_t *buf,
+                                    unsigned long index,
+                                    unsigned long pages)
+{
+       return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages);
+}
+
+static unsigned long pagemap_read(uint64_t *buf,
+                                 unsigned long index,
+                                 unsigned long pages)
+{
+       return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages);
+}
+
+static unsigned long pagemap_pfn(uint64_t val)
+{
+       unsigned long pfn;
+
+       if (val & PM_PRESENT)
+               pfn = PM_PFRAME(val);
+       else
+               pfn = 0;
+
+       return pfn;
+}
+
+
+/*
+ * page flag names
+ */
+
+static char *page_flag_name(uint64_t flags)
+{
+       static char buf[65];
+       int present;
+       int i, j;
+
+       for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+               present = (flags >> i) & 1;
+               if (!page_flag_names[i]) {
+                       if (present)
+                               fatal("unknown flag bit %d\n", i);
+                       continue;
+               }
+               buf[j++] = present ? page_flag_names[i][0] : '_';
+       }
+
+       return buf;
+}
+
+static char *page_flag_longname(uint64_t flags)
+{
+       static char buf[1024];
+       int i, n;
+
+       for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+               if (!page_flag_names[i])
+                       continue;
+               if ((flags >> i) & 1)
+                       n += snprintf(buf + n, sizeof(buf) - n, "%s,",
+                                       page_flag_names[i] + 2);
+       }
+       if (n)
+               n--;
+       buf[n] = '\0';
+
+       return buf;
+}
+
+
+/*
+ * page list and summary
+ */
+
+static void show_page_range(unsigned long voffset,
+                           unsigned long offset, uint64_t flags)
+{
+       static uint64_t      flags0;
+       static unsigned long voff;
+       static unsigned long index;
+       static unsigned long count;
+
+       if (flags == flags0 && offset == index + count &&
+           (!opt_pid || voffset == voff + count)) {
+               count++;
+               return;
+       }
+
+       if (count) {
+               if (opt_pid)
+                       printf("%lx\t", voff);
+               printf("%lx\t%lx\t%s\n",
+                               index, count, page_flag_name(flags0));
+       }
+
+       flags0 = flags;
+       index  = offset;
+       voff   = voffset;
+       count  = 1;
+}
+
+static void show_page(unsigned long voffset,
+                     unsigned long offset, uint64_t flags)
+{
+       if (opt_pid)
+               printf("%lx\t", voffset);
+       printf("%lx\t%s\n", offset, page_flag_name(flags));
+}
+
+static void show_summary(void)
+{
+       int i;
+
+       printf("             flags\tpage-count       MB"
+               "  symbolic-flags\t\t\tlong-symbolic-flags\n");
+
+       for (i = 0; i < ARRAY_SIZE(nr_pages); i++) {
+               if (nr_pages[i])
+                       printf("0x%016llx\t%10lu %8lu  %s\t%s\n",
+                               (unsigned long long)page_flags[i],
+                               nr_pages[i],
+                               pages2mb(nr_pages[i]),
+                               page_flag_name(page_flags[i]),
+                               page_flag_longname(page_flags[i]));
+       }
+
+       printf("             total\t%10lu %8lu\n",
+                       total_pages, pages2mb(total_pages));
+}
+
+
+/*
+ * page flag filters
+ */
+
+static int bit_mask_ok(uint64_t flags)
+{
+       int i;
+
+       for (i = 0; i < nr_bit_filters; i++) {
+               if (opt_bits[i] == KPF_ALL_BITS) {
+                       if ((flags & opt_mask[i]) == 0)
+                               return 0;
+               } else {
+                       if ((flags & opt_mask[i]) != opt_bits[i])
+                               return 0;
+               }
+       }
+
+       return 1;
+}
+
+static uint64_t expand_overloaded_flags(uint64_t flags)
+{
+       /* SLOB/SLUB overload several page flags */
+       if (flags & BIT(SLAB)) {
+               if (flags & BIT(PRIVATE))
+                       flags ^= BIT(PRIVATE) | BIT(SLOB_FREE);
+               if (flags & BIT(ACTIVE))
+                       flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN);
+               if (flags & BIT(ERROR))
+                       flags ^= BIT(ERROR) | BIT(SLUB_DEBUG);
+       }
+
+       /* PG_reclaim is overloaded as PG_readahead in the read path */
+       if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM))
+               flags ^= BIT(RECLAIM) | BIT(READAHEAD);
+
+       return flags;
+}
+
+static uint64_t well_known_flags(uint64_t flags)
+{
+       /* hide flags intended only for kernel hacker */
+       flags &= ~KPF_HACKERS_BITS;
+
+       /* hide non-hugeTLB compound pages */
+       if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE)))
+               flags &= ~BITS_COMPOUND;
+
+       return flags;
+}
+
+static uint64_t kpageflags_flags(uint64_t flags)
+{
+       flags = expand_overloaded_flags(flags);
+
+       if (!opt_raw)
+               flags = well_known_flags(flags);
+
+       return flags;
+}
+
+/* verify that a mountpoint is actually a debugfs instance */
+static int debugfs_valid_mountpoint(const char *debugfs)
+{
+       struct statfs st_fs;
+
+       if (statfs(debugfs, &st_fs) < 0)
+               return -ENOENT;
+       else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+               return -ENOENT;
+
+       return 0;
+}
+
+/* find the path to the mounted debugfs */
+static const char *debugfs_find_mountpoint(void)
+{
+       const char **ptr;
+       char type[100];
+       FILE *fp;
+
+       ptr = debugfs_known_mountpoints;
+       while (*ptr) {
+               if (debugfs_valid_mountpoint(*ptr) == 0) {
+                       strcpy(hwpoison_debug_fs, *ptr);
+                       return hwpoison_debug_fs;
+               }
+               ptr++;
+       }
+
+       /* give up and parse /proc/mounts */
+       fp = fopen("/proc/mounts", "r");
+       if (fp == NULL)
+               perror("Can't open /proc/mounts for read");
+
+       while (fscanf(fp, "%*s %"
+                     STR(MAX_PATH)
+                     "s %99s %*s %*d %*d\n",
+                     hwpoison_debug_fs, type) == 2) {
+               if (strcmp(type, "debugfs") == 0)
+                       break;
+       }
+       fclose(fp);
+
+       if (strcmp(type, "debugfs") != 0)
+               return NULL;
+
+       return hwpoison_debug_fs;
+}
+
+/* mount the debugfs somewhere if it's not mounted */
+
+static void debugfs_mount(void)
+{
+       const char **ptr;
+
+       /* see if it's already mounted */
+       if (debugfs_find_mountpoint())
+               return;
+
+       ptr = debugfs_known_mountpoints;
+       while (*ptr) {
+               if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) {
+                       /* save the mountpoint */
+                       strcpy(hwpoison_debug_fs, *ptr);
+                       break;
+               }
+               ptr++;
+       }
+
+       if (*ptr == NULL) {
+               perror("mount debugfs");
+               exit(EXIT_FAILURE);
+       }
+}
+
+/*
+ * page actions
+ */
+
+static void prepare_hwpoison_fd(void)
+{
+       char buf[MAX_PATH + 1];
+
+       debugfs_mount();
+
+       if (opt_hwpoison && !hwpoison_inject_fd) {
+               snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn",
+                       hwpoison_debug_fs);
+               hwpoison_inject_fd = checked_open(buf, O_WRONLY);
+       }
+
+       if (opt_unpoison && !hwpoison_forget_fd) {
+               snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn",
+                       hwpoison_debug_fs);
+               hwpoison_forget_fd = checked_open(buf, O_WRONLY);
+       }
+}
+
+static int hwpoison_page(unsigned long offset)
+{
+       char buf[100];
+       int len;
+
+       len = sprintf(buf, "0x%lx\n", offset);
+       len = write(hwpoison_inject_fd, buf, len);
+       if (len < 0) {
+               perror("hwpoison inject");
+               return len;
+       }
+       return 0;
+}
+
+static int unpoison_page(unsigned long offset)
+{
+       char buf[100];
+       int len;
+
+       len = sprintf(buf, "0x%lx\n", offset);
+       len = write(hwpoison_forget_fd, buf, len);
+       if (len < 0) {
+               perror("hwpoison forget");
+               return len;
+       }
+       return 0;
+}
+
+/*
+ * page frame walker
+ */
+
+static int hash_slot(uint64_t flags)
+{
+       int k = HASH_KEY(flags);
+       int i;
+
+       /* Explicitly reserve slot 0 for flags 0: the following logic
+        * cannot distinguish an unoccupied slot from slot (flags==0).
+        */
+       if (flags == 0)
+               return 0;
+
+       /* search through the remaining (HASH_SIZE-1) slots */
+       for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) {
+               if (!k || k >= ARRAY_SIZE(page_flags))
+                       k = 1;
+               if (page_flags[k] == 0) {
+                       page_flags[k] = flags;
+                       return k;
+               }
+               if (page_flags[k] == flags)
+                       return k;
+       }
+
+       fatal("hash table full: bump up HASH_SHIFT?\n");
+       exit(EXIT_FAILURE);
+}
+
+static void add_page(unsigned long voffset,
+                    unsigned long offset, uint64_t flags)
+{
+       flags = kpageflags_flags(flags);
+
+       if (!bit_mask_ok(flags))
+               return;
+
+       if (opt_hwpoison)
+               hwpoison_page(offset);
+       if (opt_unpoison)
+               unpoison_page(offset);
+
+       if (opt_list == 1)
+               show_page_range(voffset, offset, flags);
+       else if (opt_list == 2)
+               show_page(voffset, offset, flags);
+
+       nr_pages[hash_slot(flags)]++;
+       total_pages++;
+}
+
+#define KPAGEFLAGS_BATCH       (64 << 10)      /* 64k pages */
+static void walk_pfn(unsigned long voffset,
+                    unsigned long index,
+                    unsigned long count)
+{
+       uint64_t buf[KPAGEFLAGS_BATCH];
+       unsigned long batch;
+       long pages;
+       unsigned long i;
+
+       while (count) {
+               batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH);
+               pages = kpageflags_read(buf, index, batch);
+               if (pages == 0)
+                       break;
+
+               for (i = 0; i < pages; i++)
+                       add_page(voffset + i, index + i, buf[i]);
+
+               index += pages;
+               count -= pages;
+       }
+}
+
+#define PAGEMAP_BATCH  (64 << 10)
+static void walk_vma(unsigned long index, unsigned long count)
+{
+       uint64_t buf[PAGEMAP_BATCH];
+       unsigned long batch;
+       unsigned long pages;
+       unsigned long pfn;
+       unsigned long i;
+
+       while (count) {
+               batch = min_t(unsigned long, count, PAGEMAP_BATCH);
+               pages = pagemap_read(buf, index, batch);
+               if (pages == 0)
+                       break;
+
+               for (i = 0; i < pages; i++) {
+                       pfn = pagemap_pfn(buf[i]);
+                       if (pfn)
+                               walk_pfn(index + i, pfn, 1);
+               }
+
+               index += pages;
+               count -= pages;
+       }
+}
+
+static void walk_task(unsigned long index, unsigned long count)
+{
+       const unsigned long end = index + count;
+       unsigned long start;
+       int i = 0;
+
+       while (index < end) {
+
+               while (pg_end[i] <= index)
+                       if (++i >= nr_vmas)
+                               return;
+               if (pg_start[i] >= end)
+                       return;
+
+               start = max_t(unsigned long, pg_start[i], index);
+               index = min_t(unsigned long, pg_end[i], end);
+
+               assert(start < index);
+               walk_vma(start, index - start);
+       }
+}
+
+static void add_addr_range(unsigned long offset, unsigned long size)
+{
+       if (nr_addr_ranges >= MAX_ADDR_RANGES)
+               fatal("too many addr ranges\n");
+
+       opt_offset[nr_addr_ranges] = offset;
+       opt_size[nr_addr_ranges] = min_t(unsigned long, size, ULONG_MAX-offset);
+       nr_addr_ranges++;
+}
+
+static void walk_addr_ranges(void)
+{
+       int i;
+
+       kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY);
+
+       if (!nr_addr_ranges)
+               add_addr_range(0, ULONG_MAX);
+
+       for (i = 0; i < nr_addr_ranges; i++)
+               if (!opt_pid)
+                       walk_pfn(0, opt_offset[i], opt_size[i]);
+               else
+                       walk_task(opt_offset[i], opt_size[i]);
+
+       close(kpageflags_fd);
+}
+
+
+/*
+ * user interface
+ */
+
+static const char *page_flag_type(uint64_t flag)
+{
+       if (flag & KPF_HACKERS_BITS)
+               return "(r)";
+       if (flag & KPF_OVERLOADED_BITS)
+               return "(o)";
+       return "   ";
+}
+
+static void usage(void)
+{
+       int i, j;
+
+       printf(
+"page-types [options]\n"
+"            -r|--raw                   Raw mode, for kernel developers\n"
+"            -d|--describe flags        Describe flags\n"
+"            -a|--addr    addr-spec     Walk a range of pages\n"
+"            -b|--bits    bits-spec     Walk pages with specified bits\n"
+"            -p|--pid     pid           Walk process address space\n"
+#if 0 /* planned features */
+"            -f|--file    filename      Walk file address space\n"
+#endif
+"            -l|--list                  Show page details in ranges\n"
+"            -L|--list-each             Show page details one by one\n"
+"            -N|--no-summary            Don't show summary info\n"
+"            -X|--hwpoison              hwpoison pages\n"
+"            -x|--unpoison              unpoison pages\n"
+"            -h|--help                  Show this usage message\n"
+"flags:\n"
+"            0x10                       bitfield format, e.g.\n"
+"            anon                       bit-name, e.g.\n"
+"            0x10,anon                  comma-separated list, e.g.\n"
+"addr-spec:\n"
+"            N                          one page at offset N (unit: pages)\n"
+"            N+M                        pages range from N to N+M-1\n"
+"            N,M                        pages range from N to M-1\n"
+"            N,                         pages range from N to end\n"
+"            ,M                         pages range from 0 to M-1\n"
+"bits-spec:\n"
+"            bit1,bit2                  (flags & (bit1|bit2)) != 0\n"
+"            bit1,bit2=bit1             (flags & (bit1|bit2)) == bit1\n"
+"            bit1,~bit2                 (flags & (bit1|bit2)) == bit1\n"
+"            =bit1,bit2                 flags == (bit1|bit2)\n"
+"bit-names:\n"
+       );
+
+       for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+               if (!page_flag_names[i])
+                       continue;
+               printf("%16s%s", page_flag_names[i] + 2,
+                                page_flag_type(1ULL << i));
+               if (++j > 3) {
+                       j = 0;
+                       putchar('\n');
+               }
+       }
+       printf("\n                                   "
+               "(r) raw mode bits  (o) overloaded bits\n");
+}
+
+static unsigned long long parse_number(const char *str)
+{
+       unsigned long long n;
+
+       n = strtoll(str, NULL, 0);
+
+       if (n == 0 && str[0] != '0')
+               fatal("invalid name or number: %s\n", str);
+
+       return n;
+}
+
+static void parse_pid(const char *str)
+{
+       FILE *file;
+       char buf[5000];
+
+       opt_pid = parse_number(str);
+
+       sprintf(buf, "/proc/%d/pagemap", opt_pid);
+       pagemap_fd = checked_open(buf, O_RDONLY);
+
+       sprintf(buf, "/proc/%d/maps", opt_pid);
+       file = fopen(buf, "r");
+       if (!file) {
+               perror(buf);
+               exit(EXIT_FAILURE);
+       }
+
+       while (fgets(buf, sizeof(buf), file) != NULL) {
+               unsigned long vm_start;
+               unsigned long vm_end;
+               unsigned long long pgoff;
+               int major, minor;
+               char r, w, x, s;
+               unsigned long ino;
+               int n;
+
+               n = sscanf(buf, "%lx-%lx %c%c%c%c %llx %x:%x %lu",
+                          &vm_start,
+                          &vm_end,
+                          &r, &w, &x, &s,
+                          &pgoff,
+                          &major, &minor,
+                          &ino);
+               if (n < 10) {
+                       fprintf(stderr, "unexpected line: %s\n", buf);
+                       continue;
+               }
+               pg_start[nr_vmas] = vm_start / page_size;
+               pg_end[nr_vmas] = vm_end / page_size;
+               if (++nr_vmas >= MAX_VMAS) {
+                       fprintf(stderr, "too many VMAs\n");
+                       break;
+               }
+       }
+       fclose(file);
+}
+
+static void parse_file(const char *name)
+{
+}
+
+static void parse_addr_range(const char *optarg)
+{
+       unsigned long offset;
+       unsigned long size;
+       char *p;
+
+       p = strchr(optarg, ',');
+       if (!p)
+               p = strchr(optarg, '+');
+
+       if (p == optarg) {
+               offset = 0;
+               size   = parse_number(p + 1);
+       } else if (p) {
+               offset = parse_number(optarg);
+               if (p[1] == '\0')
+                       size = ULONG_MAX;
+               else {
+                       size = parse_number(p + 1);
+                       if (*p == ',') {
+                               if (size < offset)
+                                       fatal("invalid range: %lu,%lu\n",
+                                                       offset, size);
+                               size -= offset;
+                       }
+               }
+       } else {
+               offset = parse_number(optarg);
+               size   = 1;
+       }
+
+       add_addr_range(offset, size);
+}
+
+static void add_bits_filter(uint64_t mask, uint64_t bits)
+{
+       if (nr_bit_filters >= MAX_BIT_FILTERS)
+               fatal("too much bit filters\n");
+
+       opt_mask[nr_bit_filters] = mask;
+       opt_bits[nr_bit_filters] = bits;
+       nr_bit_filters++;
+}
+
+static uint64_t parse_flag_name(const char *str, int len)
+{
+       int i;
+
+       if (!*str || !len)
+               return 0;
+
+       if (len <= 8 && !strncmp(str, "compound", len))
+               return BITS_COMPOUND;
+
+       for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
+               if (!page_flag_names[i])
+                       continue;
+               if (!strncmp(str, page_flag_names[i] + 2, len))
+                       return 1ULL << i;
+       }
+
+       return parse_number(str);
+}
+
+static uint64_t parse_flag_names(const char *str, int all)
+{
+       const char *p    = str;
+       uint64_t   flags = 0;
+
+       while (1) {
+               if (*p == ',' || *p == '=' || *p == '\0') {
+                       if ((*str != '~') || (*str == '~' && all && *++str))
+                               flags |= parse_flag_name(str, p - str);
+                       if (*p != ',')
+                               break;
+                       str = p + 1;
+               }
+               p++;
+       }
+
+       return flags;
+}
+
+static void parse_bits_mask(const char *optarg)
+{
+       uint64_t mask;
+       uint64_t bits;
+       const char *p;
+
+       p = strchr(optarg, '=');
+       if (p == optarg) {
+               mask = KPF_ALL_BITS;
+               bits = parse_flag_names(p + 1, 0);
+       } else if (p) {
+               mask = parse_flag_names(optarg, 0);
+               bits = parse_flag_names(p + 1, 0);
+       } else if (strchr(optarg, '~')) {
+               mask = parse_flag_names(optarg, 1);
+               bits = parse_flag_names(optarg, 0);
+       } else {
+               mask = parse_flag_names(optarg, 0);
+               bits = KPF_ALL_BITS;
+       }
+
+       add_bits_filter(mask, bits);
+}
+
+static void describe_flags(const char *optarg)
+{
+       uint64_t flags = parse_flag_names(optarg, 0);
+
+       printf("0x%016llx\t%s\t%s\n",
+               (unsigned long long)flags,
+               page_flag_name(flags),
+               page_flag_longname(flags));
+}
+
+static const struct option opts[] = {
+       { "raw"       , 0, NULL, 'r' },
+       { "pid"       , 1, NULL, 'p' },
+       { "file"      , 1, NULL, 'f' },
+       { "addr"      , 1, NULL, 'a' },
+       { "bits"      , 1, NULL, 'b' },
+       { "describe"  , 1, NULL, 'd' },
+       { "list"      , 0, NULL, 'l' },
+       { "list-each" , 0, NULL, 'L' },
+       { "no-summary", 0, NULL, 'N' },
+       { "hwpoison"  , 0, NULL, 'X' },
+       { "unpoison"  , 0, NULL, 'x' },
+       { "help"      , 0, NULL, 'h' },
+       { NULL        , 0, NULL, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+       int c;
+
+       page_size = getpagesize();
+
+       while ((c = getopt_long(argc, argv,
+                               "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) {
+               switch (c) {
+               case 'r':
+                       opt_raw = 1;
+                       break;
+               case 'p':
+                       parse_pid(optarg);
+                       break;
+               case 'f':
+                       parse_file(optarg);
+                       break;
+               case 'a':
+                       parse_addr_range(optarg);
+                       break;
+               case 'b':
+                       parse_bits_mask(optarg);
+                       break;
+               case 'd':
+                       describe_flags(optarg);
+                       exit(0);
+               case 'l':
+                       opt_list = 1;
+                       break;
+               case 'L':
+                       opt_list = 2;
+                       break;
+               case 'N':
+                       opt_no_summary = 1;
+                       break;
+               case 'X':
+                       opt_hwpoison = 1;
+                       prepare_hwpoison_fd();
+                       break;
+               case 'x':
+                       opt_unpoison = 1;
+                       prepare_hwpoison_fd();
+                       break;
+               case 'h':
+                       usage();
+                       exit(0);
+               default:
+                       usage();
+                       exit(1);
+               }
+       }
+
+       if (opt_list && opt_pid)
+               printf("voffset\t");
+       if (opt_list == 1)
+               printf("offset\tlen\tflags\n");
+       if (opt_list == 2)
+               printf("offset\tflags\n");
+
+       walk_addr_ranges();
+
+       if (opt_list == 1)
+               show_page_range(0, 0, 0);  /* drain the buffer */
+
+       if (opt_no_summary)
+               return 0;
+
+       if (opt_list)
+               printf("\n\n");
+
+       show_summary();
+
+       return 0;
+}
diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
new file mode 100644 (file)
index 0000000..164cbcf
--- /dev/null
@@ -0,0 +1,1393 @@
+/*
+ * Slabinfo: Tool to get reports about slabs
+ *
+ * (C) 2007 sgi, Christoph Lameter
+ * (C) 2011 Linux Foundation, Christoph Lameter
+ *
+ * Compile with:
+ *
+ * gcc -o slabinfo slabinfo.c
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <strings.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <regex.h>
+#include <errno.h>
+
+#define MAX_SLABS 500
+#define MAX_ALIASES 500
+#define MAX_NODES 1024
+
+struct slabinfo {
+       char *name;
+       int alias;
+       int refs;
+       int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
+       int hwcache_align, object_size, objs_per_slab;
+       int sanity_checks, slab_size, store_user, trace;
+       int order, poison, reclaim_account, red_zone;
+       unsigned long partial, objects, slabs, objects_partial, objects_total;
+       unsigned long alloc_fastpath, alloc_slowpath;
+       unsigned long free_fastpath, free_slowpath;
+       unsigned long free_frozen, free_add_partial, free_remove_partial;
+       unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill;
+       unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
+       unsigned long deactivate_to_head, deactivate_to_tail;
+       unsigned long deactivate_remote_frees, order_fallback;
+       unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
+       unsigned long alloc_node_mismatch, deactivate_bypass;
+       unsigned long cpu_partial_alloc, cpu_partial_free;
+       int numa[MAX_NODES];
+       int numa_partial[MAX_NODES];
+} slabinfo[MAX_SLABS];
+
+struct aliasinfo {
+       char *name;
+       char *ref;
+       struct slabinfo *slab;
+} aliasinfo[MAX_ALIASES];
+
+int slabs = 0;
+int actual_slabs = 0;
+int aliases = 0;
+int alias_targets = 0;
+int highest_node = 0;
+
+char buffer[4096];
+
+int show_empty = 0;
+int show_report = 0;
+int show_alias = 0;
+int show_slab = 0;
+int skip_zero = 1;
+int show_numa = 0;
+int show_track = 0;
+int show_first_alias = 0;
+int validate = 0;
+int shrink = 0;
+int show_inverted = 0;
+int show_single_ref = 0;
+int show_totals = 0;
+int sort_size = 0;
+int sort_active = 0;
+int set_debug = 0;
+int show_ops = 0;
+int show_activity = 0;
+
+/* Debug options */
+int sanity = 0;
+int redzone = 0;
+int poison = 0;
+int tracking = 0;
+int tracing = 0;
+
+int page_size;
+
+regex_t pattern;
+
+static void fatal(const char *x, ...)
+{
+       va_list ap;
+
+       va_start(ap, x);
+       vfprintf(stderr, x, ap);
+       va_end(ap);
+       exit(EXIT_FAILURE);
+}
+
+static void usage(void)
+{
+       printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n"
+               "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
+               "-a|--aliases           Show aliases\n"
+               "-A|--activity          Most active slabs first\n"
+               "-d<options>|--debug=<options> Set/Clear Debug options\n"
+               "-D|--display-active    Switch line format to activity\n"
+               "-e|--empty             Show empty slabs\n"
+               "-f|--first-alias       Show first alias\n"
+               "-h|--help              Show usage information\n"
+               "-i|--inverted          Inverted list\n"
+               "-l|--slabs             Show slabs\n"
+               "-n|--numa              Show NUMA information\n"
+               "-o|--ops               Show kmem_cache_ops\n"
+               "-s|--shrink            Shrink slabs\n"
+               "-r|--report            Detailed report on single slabs\n"
+               "-S|--Size              Sort by size\n"
+               "-t|--tracking          Show alloc/free information\n"
+               "-T|--Totals            Show summary information\n"
+               "-v|--validate          Validate slabs\n"
+               "-z|--zero              Include empty slabs\n"
+               "-1|--1ref              Single reference\n"
+               "\nValid debug options (FZPUT may be combined)\n"
+               "a / A          Switch on all debug options (=FZUP)\n"
+               "-              Switch off all debug options\n"
+               "f / F          Sanity Checks (SLAB_DEBUG_FREE)\n"
+               "z / Z          Redzoning\n"
+               "p / P          Poisoning\n"
+               "u / U          Tracking\n"
+               "t / T          Tracing\n"
+       );
+}
+
+static unsigned long read_obj(const char *name)
+{
+       FILE *f = fopen(name, "r");
+
+       if (!f)
+               buffer[0] = 0;
+       else {
+               if (!fgets(buffer, sizeof(buffer), f))
+                       buffer[0] = 0;
+               fclose(f);
+               if (buffer[strlen(buffer)] == '\n')
+                       buffer[strlen(buffer)] = 0;
+       }
+       return strlen(buffer);
+}
+
+
+/*
+ * Get the contents of an attribute
+ */
+static unsigned long get_obj(const char *name)
+{
+       if (!read_obj(name))
+               return 0;
+
+       return atol(buffer);
+}
+
+static unsigned long get_obj_and_str(const char *name, char **x)
+{
+       unsigned long result = 0;
+       char *p;
+
+       *x = NULL;
+
+       if (!read_obj(name)) {
+               x = NULL;
+               return 0;
+       }
+       result = strtoul(buffer, &p, 10);
+       while (*p == ' ')
+               p++;
+       if (*p)
+               *x = strdup(p);
+       return result;
+}
+
+static void set_obj(struct slabinfo *s, const char *name, int n)
+{
+       char x[100];
+       FILE *f;
+
+       snprintf(x, 100, "%s/%s", s->name, name);
+       f = fopen(x, "w");
+       if (!f)
+               fatal("Cannot write to %s\n", x);
+
+       fprintf(f, "%d\n", n);
+       fclose(f);
+}
+
+static unsigned long read_slab_obj(struct slabinfo *s, const char *name)
+{
+       char x[100];
+       FILE *f;
+       size_t l;
+
+       snprintf(x, 100, "%s/%s", s->name, name);
+       f = fopen(x, "r");
+       if (!f) {
+               buffer[0] = 0;
+               l = 0;
+       } else {
+               l = fread(buffer, 1, sizeof(buffer), f);
+               buffer[l] = 0;
+               fclose(f);
+       }
+       return l;
+}
+
+
+/*
+ * Put a size string together
+ */
+static int store_size(char *buffer, unsigned long value)
+{
+       unsigned long divisor = 1;
+       char trailer = 0;
+       int n;
+
+       if (value > 1000000000UL) {
+               divisor = 100000000UL;
+               trailer = 'G';
+       } else if (value > 1000000UL) {
+               divisor = 100000UL;
+               trailer = 'M';
+       } else if (value > 1000UL) {
+               divisor = 100;
+               trailer = 'K';
+       }
+
+       value /= divisor;
+       n = sprintf(buffer, "%ld",value);
+       if (trailer) {
+               buffer[n] = trailer;
+               n++;
+               buffer[n] = 0;
+       }
+       if (divisor != 1) {
+               memmove(buffer + n - 2, buffer + n - 3, 4);
+               buffer[n-2] = '.';
+               n++;
+       }
+       return n;
+}
+
+static void decode_numa_list(int *numa, char *t)
+{
+       int node;
+       int nr;
+
+       memset(numa, 0, MAX_NODES * sizeof(int));
+
+       if (!t)
+               return;
+
+       while (*t == 'N') {
+               t++;
+               node = strtoul(t, &t, 10);
+               if (*t == '=') {
+                       t++;
+                       nr = strtoul(t, &t, 10);
+                       numa[node] = nr;
+                       if (node > highest_node)
+                               highest_node = node;
+               }
+               while (*t == ' ')
+                       t++;
+       }
+}
+
+static void slab_validate(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       set_obj(s, "validate", 1);
+}
+
+static void slab_shrink(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       set_obj(s, "shrink", 1);
+}
+
+int line = 0;
+
+static void first_line(void)
+{
+       if (show_activity)
+               printf("Name                   Objects      Alloc       Free   %%Fast Fallb O CmpX   UL\n");
+       else
+               printf("Name                   Objects Objsize    Space "
+                       "Slabs/Part/Cpu  O/S O %%Fr %%Ef Flg\n");
+}
+
+/*
+ * Find the shortest alias of a slab
+ */
+static struct aliasinfo *find_one_alias(struct slabinfo *find)
+{
+       struct aliasinfo *a;
+       struct aliasinfo *best = NULL;
+
+       for(a = aliasinfo;a < aliasinfo + aliases; a++) {
+               if (a->slab == find &&
+                       (!best || strlen(best->name) < strlen(a->name))) {
+                               best = a;
+                               if (strncmp(a->name,"kmall", 5) == 0)
+                                       return best;
+                       }
+       }
+       return best;
+}
+
+static unsigned long slab_size(struct slabinfo *s)
+{
+       return  s->slabs * (page_size << s->order);
+}
+
+static unsigned long slab_activity(struct slabinfo *s)
+{
+       return  s->alloc_fastpath + s->free_fastpath +
+               s->alloc_slowpath + s->free_slowpath;
+}
+
+static void slab_numa(struct slabinfo *s, int mode)
+{
+       int node;
+
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (!highest_node) {
+               printf("\n%s: No NUMA information available.\n", s->name);
+               return;
+       }
+
+       if (skip_zero && !s->slabs)
+               return;
+
+       if (!line) {
+               printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
+               for(node = 0; node <= highest_node; node++)
+                       printf(" %4d", node);
+               printf("\n----------------------");
+               for(node = 0; node <= highest_node; node++)
+                       printf("-----");
+               printf("\n");
+       }
+       printf("%-21s ", mode ? "All slabs" : s->name);
+       for(node = 0; node <= highest_node; node++) {
+               char b[20];
+
+               store_size(b, s->numa[node]);
+               printf(" %4s", b);
+       }
+       printf("\n");
+       if (mode) {
+               printf("%-21s ", "Partial slabs");
+               for(node = 0; node <= highest_node; node++) {
+                       char b[20];
+
+                       store_size(b, s->numa_partial[node]);
+                       printf(" %4s", b);
+               }
+               printf("\n");
+       }
+       line++;
+}
+
+static void show_tracking(struct slabinfo *s)
+{
+       printf("\n%s: Kernel object allocation\n", s->name);
+       printf("-----------------------------------------------------------------------\n");
+       if (read_slab_obj(s, "alloc_calls"))
+               printf("%s", buffer);
+       else
+               printf("No Data\n");
+
+       printf("\n%s: Kernel object freeing\n", s->name);
+       printf("------------------------------------------------------------------------\n");
+       if (read_slab_obj(s, "free_calls"))
+               printf("%s", buffer);
+       else
+               printf("No Data\n");
+
+}
+
+static void ops(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (read_slab_obj(s, "ops")) {
+               printf("\n%s: kmem_cache operations\n", s->name);
+               printf("--------------------------------------------\n");
+               printf("%s", buffer);
+       } else
+               printf("\n%s has no kmem_cache operations\n", s->name);
+}
+
+static const char *onoff(int x)
+{
+       if (x)
+               return "On ";
+       return "Off";
+}
+
+static void slab_stats(struct slabinfo *s)
+{
+       unsigned long total_alloc;
+       unsigned long total_free;
+       unsigned long total;
+
+       if (!s->alloc_slab)
+               return;
+
+       total_alloc = s->alloc_fastpath + s->alloc_slowpath;
+       total_free = s->free_fastpath + s->free_slowpath;
+
+       if (!total_alloc)
+               return;
+
+       printf("\n");
+       printf("Slab Perf Counter       Alloc     Free %%Al %%Fr\n");
+       printf("--------------------------------------------------\n");
+       printf("Fastpath             %8lu %8lu %3lu %3lu\n",
+               s->alloc_fastpath, s->free_fastpath,
+               s->alloc_fastpath * 100 / total_alloc,
+               s->free_fastpath * 100 / total_free);
+       printf("Slowpath             %8lu %8lu %3lu %3lu\n",
+               total_alloc - s->alloc_fastpath, s->free_slowpath,
+               (total_alloc - s->alloc_fastpath) * 100 / total_alloc,
+               s->free_slowpath * 100 / total_free);
+       printf("Page Alloc           %8lu %8lu %3lu %3lu\n",
+               s->alloc_slab, s->free_slab,
+               s->alloc_slab * 100 / total_alloc,
+               s->free_slab * 100 / total_free);
+       printf("Add partial          %8lu %8lu %3lu %3lu\n",
+               s->deactivate_to_head + s->deactivate_to_tail,
+               s->free_add_partial,
+               (s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc,
+               s->free_add_partial * 100 / total_free);
+       printf("Remove partial       %8lu %8lu %3lu %3lu\n",
+               s->alloc_from_partial, s->free_remove_partial,
+               s->alloc_from_partial * 100 / total_alloc,
+               s->free_remove_partial * 100 / total_free);
+
+       printf("Cpu partial list     %8lu %8lu %3lu %3lu\n",
+               s->cpu_partial_alloc, s->cpu_partial_free,
+               s->cpu_partial_alloc * 100 / total_alloc,
+               s->cpu_partial_free * 100 / total_free);
+
+       printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
+               s->deactivate_remote_frees, s->free_frozen,
+               s->deactivate_remote_frees * 100 / total_alloc,
+               s->free_frozen * 100 / total_free);
+
+       printf("Total                %8lu %8lu\n\n", total_alloc, total_free);
+
+       if (s->cpuslab_flush)
+               printf("Flushes %8lu\n", s->cpuslab_flush);
+
+       total = s->deactivate_full + s->deactivate_empty +
+                       s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
+
+       if (total) {
+               printf("\nSlab Deactivation             Ocurrences  %%\n");
+               printf("-------------------------------------------------\n");
+               printf("Slab full                     %7lu  %3lu%%\n",
+                       s->deactivate_full, (s->deactivate_full * 100) / total);
+               printf("Slab empty                    %7lu  %3lu%%\n",
+                       s->deactivate_empty, (s->deactivate_empty * 100) / total);
+               printf("Moved to head of partial list %7lu  %3lu%%\n",
+                       s->deactivate_to_head, (s->deactivate_to_head * 100) / total);
+               printf("Moved to tail of partial list %7lu  %3lu%%\n",
+                       s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
+               printf("Deactivation bypass           %7lu  %3lu%%\n",
+                       s->deactivate_bypass, (s->deactivate_bypass * 100) / total);
+               printf("Refilled from foreign frees   %7lu  %3lu%%\n",
+                       s->alloc_refill, (s->alloc_refill * 100) / total);
+               printf("Node mismatch                 %7lu  %3lu%%\n",
+                       s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
+       }
+
+       if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail)
+               printf("\nCmpxchg_double Looping\n------------------------\n");
+               printf("Locked Cmpxchg Double redos   %lu\nUnlocked Cmpxchg Double redos %lu\n",
+                       s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
+}
+
+static void report(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       printf("\nSlabcache: %-20s  Aliases: %2d Order : %2d Objects: %lu\n",
+               s->name, s->aliases, s->order, s->objects);
+       if (s->hwcache_align)
+               printf("** Hardware cacheline aligned\n");
+       if (s->cache_dma)
+               printf("** Memory is allocated in a special DMA zone\n");
+       if (s->destroy_by_rcu)
+               printf("** Slabs are destroyed via RCU\n");
+       if (s->reclaim_account)
+               printf("** Reclaim accounting active\n");
+
+       printf("\nSizes (bytes)     Slabs              Debug                Memory\n");
+       printf("------------------------------------------------------------------------\n");
+       printf("Object : %7d  Total  : %7ld   Sanity Checks : %s  Total: %7ld\n",
+                       s->object_size, s->slabs, onoff(s->sanity_checks),
+                       s->slabs * (page_size << s->order));
+       printf("SlabObj: %7d  Full   : %7ld   Redzoning     : %s  Used : %7ld\n",
+                       s->slab_size, s->slabs - s->partial - s->cpu_slabs,
+                       onoff(s->red_zone), s->objects * s->object_size);
+       printf("SlabSiz: %7d  Partial: %7ld   Poisoning     : %s  Loss : %7ld\n",
+                       page_size << s->order, s->partial, onoff(s->poison),
+                       s->slabs * (page_size << s->order) - s->objects * s->object_size);
+       printf("Loss   : %7d  CpuSlab: %7d   Tracking      : %s  Lalig: %7ld\n",
+                       s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
+                       (s->slab_size - s->object_size) * s->objects);
+       printf("Align  : %7d  Objects: %7d   Tracing       : %s  Lpadd: %7ld\n",
+                       s->align, s->objs_per_slab, onoff(s->trace),
+                       ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
+                       s->slabs);
+
+       ops(s);
+       show_tracking(s);
+       slab_numa(s, 1);
+       slab_stats(s);
+}
+
+static void slabcache(struct slabinfo *s)
+{
+       char size_str[20];
+       char dist_str[40];
+       char flags[20];
+       char *p = flags;
+
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (actual_slabs == 1) {
+               report(s);
+               return;
+       }
+
+       if (skip_zero && !show_empty && !s->slabs)
+               return;
+
+       if (show_empty && s->slabs)
+               return;
+
+       store_size(size_str, slab_size(s));
+       snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs,
+                                               s->partial, s->cpu_slabs);
+
+       if (!line++)
+               first_line();
+
+       if (s->aliases)
+               *p++ = '*';
+       if (s->cache_dma)
+               *p++ = 'd';
+       if (s->hwcache_align)
+               *p++ = 'A';
+       if (s->poison)
+               *p++ = 'P';
+       if (s->reclaim_account)
+               *p++ = 'a';
+       if (s->red_zone)
+               *p++ = 'Z';
+       if (s->sanity_checks)
+               *p++ = 'F';
+       if (s->store_user)
+               *p++ = 'U';
+       if (s->trace)
+               *p++ = 'T';
+
+       *p = 0;
+       if (show_activity) {
+               unsigned long total_alloc;
+               unsigned long total_free;
+
+               total_alloc = s->alloc_fastpath + s->alloc_slowpath;
+               total_free = s->free_fastpath + s->free_slowpath;
+
+               printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n",
+                       s->name, s->objects,
+                       total_alloc, total_free,
+                       total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
+                       total_free ? (s->free_fastpath * 100 / total_free) : 0,
+                       s->order_fallback, s->order, s->cmpxchg_double_fail,
+                       s->cmpxchg_double_cpu_fail);
+       }
+       else
+               printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
+                       s->name, s->objects, s->object_size, size_str, dist_str,
+                       s->objs_per_slab, s->order,
+                       s->slabs ? (s->partial * 100) / s->slabs : 100,
+                       s->slabs ? (s->objects * s->object_size * 100) /
+                               (s->slabs * (page_size << s->order)) : 100,
+                       flags);
+}
+
+/*
+ * Analyze debug options. Return false if something is amiss.
+ */
+static int debug_opt_scan(char *opt)
+{
+       if (!opt || !opt[0] || strcmp(opt, "-") == 0)
+               return 1;
+
+       if (strcasecmp(opt, "a") == 0) {
+               sanity = 1;
+               poison = 1;
+               redzone = 1;
+               tracking = 1;
+               return 1;
+       }
+
+       for ( ; *opt; opt++)
+               switch (*opt) {
+               case 'F' : case 'f':
+                       if (sanity)
+                               return 0;
+                       sanity = 1;
+                       break;
+               case 'P' : case 'p':
+                       if (poison)
+                               return 0;
+                       poison = 1;
+                       break;
+
+               case 'Z' : case 'z':
+                       if (redzone)
+                               return 0;
+                       redzone = 1;
+                       break;
+
+               case 'U' : case 'u':
+                       if (tracking)
+                               return 0;
+                       tracking = 1;
+                       break;
+
+               case 'T' : case 't':
+                       if (tracing)
+                               return 0;
+                       tracing = 1;
+                       break;
+               default:
+                       return 0;
+               }
+       return 1;
+}
+
+static int slab_empty(struct slabinfo *s)
+{
+       if (s->objects > 0)
+               return 0;
+
+       /*
+        * We may still have slabs even if there are no objects. Shrinking will
+        * remove them.
+        */
+       if (s->slabs != 0)
+               set_obj(s, "shrink", 1);
+
+       return 1;
+}
+
+static void slab_debug(struct slabinfo *s)
+{
+       if (strcmp(s->name, "*") == 0)
+               return;
+
+       if (sanity && !s->sanity_checks) {
+               set_obj(s, "sanity", 1);
+       }
+       if (!sanity && s->sanity_checks) {
+               if (slab_empty(s))
+                       set_obj(s, "sanity", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
+       }
+       if (redzone && !s->red_zone) {
+               if (slab_empty(s))
+                       set_obj(s, "red_zone", 1);
+               else
+                       fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
+       }
+       if (!redzone && s->red_zone) {
+               if (slab_empty(s))
+                       set_obj(s, "red_zone", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
+       }
+       if (poison && !s->poison) {
+               if (slab_empty(s))
+                       set_obj(s, "poison", 1);
+               else
+                       fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
+       }
+       if (!poison && s->poison) {
+               if (slab_empty(s))
+                       set_obj(s, "poison", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
+       }
+       if (tracking && !s->store_user) {
+               if (slab_empty(s))
+                       set_obj(s, "store_user", 1);
+               else
+                       fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
+       }
+       if (!tracking && s->store_user) {
+               if (slab_empty(s))
+                       set_obj(s, "store_user", 0);
+               else
+                       fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
+       }
+       if (tracing && !s->trace) {
+               if (slabs == 1)
+                       set_obj(s, "trace", 1);
+               else
+                       fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
+       }
+       if (!tracing && s->trace)
+               set_obj(s, "trace", 1);
+}
+
+static void totals(void)
+{
+       struct slabinfo *s;
+
+       int used_slabs = 0;
+       char b1[20], b2[20], b3[20], b4[20];
+       unsigned long long max = 1ULL << 63;
+
+       /* Object size */
+       unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
+
+       /* Number of partial slabs in a slabcache */
+       unsigned long long min_partial = max, max_partial = 0,
+                               avg_partial, total_partial = 0;
+
+       /* Number of slabs in a slab cache */
+       unsigned long long min_slabs = max, max_slabs = 0,
+                               avg_slabs, total_slabs = 0;
+
+       /* Size of the whole slab */
+       unsigned long long min_size = max, max_size = 0,
+                               avg_size, total_size = 0;
+
+       /* Bytes used for object storage in a slab */
+       unsigned long long min_used = max, max_used = 0,
+                               avg_used, total_used = 0;
+
+       /* Waste: Bytes used for alignment and padding */
+       unsigned long long min_waste = max, max_waste = 0,
+                               avg_waste, total_waste = 0;
+       /* Number of objects in a slab */
+       unsigned long long min_objects = max, max_objects = 0,
+                               avg_objects, total_objects = 0;
+       /* Waste per object */
+       unsigned long long min_objwaste = max,
+                               max_objwaste = 0, avg_objwaste,
+                               total_objwaste = 0;
+
+       /* Memory per object */
+       unsigned long long min_memobj = max,
+                               max_memobj = 0, avg_memobj,
+                               total_objsize = 0;
+
+       /* Percentage of partial slabs per slab */
+       unsigned long min_ppart = 100, max_ppart = 0,
+                               avg_ppart, total_ppart = 0;
+
+       /* Number of objects in partial slabs */
+       unsigned long min_partobj = max, max_partobj = 0,
+                               avg_partobj, total_partobj = 0;
+
+       /* Percentage of partial objects of all objects in a slab */
+       unsigned long min_ppartobj = 100, max_ppartobj = 0,
+                               avg_ppartobj, total_ppartobj = 0;
+
+
+       for (s = slabinfo; s < slabinfo + slabs; s++) {
+               unsigned long long size;
+               unsigned long used;
+               unsigned long long wasted;
+               unsigned long long objwaste;
+               unsigned long percentage_partial_slabs;
+               unsigned long percentage_partial_objs;
+
+               if (!s->slabs || !s->objects)
+                       continue;
+
+               used_slabs++;
+
+               size = slab_size(s);
+               used = s->objects * s->object_size;
+               wasted = size - used;
+               objwaste = s->slab_size - s->object_size;
+
+               percentage_partial_slabs = s->partial * 100 / s->slabs;
+               if (percentage_partial_slabs > 100)
+                       percentage_partial_slabs = 100;
+
+               percentage_partial_objs = s->objects_partial * 100
+                                                       / s->objects;
+
+               if (percentage_partial_objs > 100)
+                       percentage_partial_objs = 100;
+
+               if (s->object_size < min_objsize)
+                       min_objsize = s->object_size;
+               if (s->partial < min_partial)
+                       min_partial = s->partial;
+               if (s->slabs < min_slabs)
+                       min_slabs = s->slabs;
+               if (size < min_size)
+                       min_size = size;
+               if (wasted < min_waste)
+                       min_waste = wasted;
+               if (objwaste < min_objwaste)
+                       min_objwaste = objwaste;
+               if (s->objects < min_objects)
+                       min_objects = s->objects;
+               if (used < min_used)
+                       min_used = used;
+               if (s->objects_partial < min_partobj)
+                       min_partobj = s->objects_partial;
+               if (percentage_partial_slabs < min_ppart)
+                       min_ppart = percentage_partial_slabs;
+               if (percentage_partial_objs < min_ppartobj)
+                       min_ppartobj = percentage_partial_objs;
+               if (s->slab_size < min_memobj)
+                       min_memobj = s->slab_size;
+
+               if (s->object_size > max_objsize)
+                       max_objsize = s->object_size;
+               if (s->partial > max_partial)
+                       max_partial = s->partial;
+               if (s->slabs > max_slabs)
+                       max_slabs = s->slabs;
+               if (size > max_size)
+                       max_size = size;
+               if (wasted > max_waste)
+                       max_waste = wasted;
+               if (objwaste > max_objwaste)
+                       max_objwaste = objwaste;
+               if (s->objects > max_objects)
+                       max_objects = s->objects;
+               if (used > max_used)
+                       max_used = used;
+               if (s->objects_partial > max_partobj)
+                       max_partobj = s->objects_partial;
+               if (percentage_partial_slabs > max_ppart)
+                       max_ppart = percentage_partial_slabs;
+               if (percentage_partial_objs > max_ppartobj)
+                       max_ppartobj = percentage_partial_objs;
+               if (s->slab_size > max_memobj)
+                       max_memobj = s->slab_size;
+
+               total_partial += s->partial;
+               total_slabs += s->slabs;
+               total_size += size;
+               total_waste += wasted;
+
+               total_objects += s->objects;
+               total_used += used;
+               total_partobj += s->objects_partial;
+               total_ppart += percentage_partial_slabs;
+               total_ppartobj += percentage_partial_objs;
+
+               total_objwaste += s->objects * objwaste;
+               total_objsize += s->objects * s->slab_size;
+       }
+
+       if (!total_objects) {
+               printf("No objects\n");
+               return;
+       }
+       if (!used_slabs) {
+               printf("No slabs\n");
+               return;
+       }
+
+       /* Per slab averages */
+       avg_partial = total_partial / used_slabs;
+       avg_slabs = total_slabs / used_slabs;
+       avg_size = total_size / used_slabs;
+       avg_waste = total_waste / used_slabs;
+
+       avg_objects = total_objects / used_slabs;
+       avg_used = total_used / used_slabs;
+       avg_partobj = total_partobj / used_slabs;
+       avg_ppart = total_ppart / used_slabs;
+       avg_ppartobj = total_ppartobj / used_slabs;
+
+       /* Per object object sizes */
+       avg_objsize = total_used / total_objects;
+       avg_objwaste = total_objwaste / total_objects;
+       avg_partobj = total_partobj * 100 / total_objects;
+       avg_memobj = total_objsize / total_objects;
+
+       printf("Slabcache Totals\n");
+       printf("----------------\n");
+       printf("Slabcaches : %3d      Aliases  : %3d->%-3d Active: %3d\n",
+                       slabs, aliases, alias_targets, used_slabs);
+
+       store_size(b1, total_size);store_size(b2, total_waste);
+       store_size(b3, total_waste * 100 / total_used);
+       printf("Memory used: %6s   # Loss   : %6s   MRatio:%6s%%\n", b1, b2, b3);
+
+       store_size(b1, total_objects);store_size(b2, total_partobj);
+       store_size(b3, total_partobj * 100 / total_objects);
+       printf("# Objects  : %6s   # PartObj: %6s   ORatio:%6s%%\n", b1, b2, b3);
+
+       printf("\n");
+       printf("Per Cache    Average         Min         Max       Total\n");
+       printf("---------------------------------------------------------\n");
+
+       store_size(b1, avg_objects);store_size(b2, min_objects);
+       store_size(b3, max_objects);store_size(b4, total_objects);
+       printf("#Objects  %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_slabs);store_size(b2, min_slabs);
+       store_size(b3, max_slabs);store_size(b4, total_slabs);
+       printf("#Slabs    %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_partial);store_size(b2, min_partial);
+       store_size(b3, max_partial);store_size(b4, total_partial);
+       printf("#PartSlab %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+       store_size(b1, avg_ppart);store_size(b2, min_ppart);
+       store_size(b3, max_ppart);
+       store_size(b4, total_partial * 100  / total_slabs);
+       printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_partobj);store_size(b2, min_partobj);
+       store_size(b3, max_partobj);
+       store_size(b4, total_partobj);
+       printf("PartObjs  %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
+       store_size(b3, max_ppartobj);
+       store_size(b4, total_partobj * 100 / total_objects);
+       printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_size);store_size(b2, min_size);
+       store_size(b3, max_size);store_size(b4, total_size);
+       printf("Memory    %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_used);store_size(b2, min_used);
+       store_size(b3, max_used);store_size(b4, total_used);
+       printf("Used      %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       store_size(b1, avg_waste);store_size(b2, min_waste);
+       store_size(b3, max_waste);store_size(b4, total_waste);
+       printf("Loss      %10s  %10s  %10s  %10s\n",
+                       b1,     b2,     b3,     b4);
+
+       printf("\n");
+       printf("Per Object   Average         Min         Max\n");
+       printf("---------------------------------------------\n");
+
+       store_size(b1, avg_memobj);store_size(b2, min_memobj);
+       store_size(b3, max_memobj);
+       printf("Memory    %10s  %10s  %10s\n",
+                       b1,     b2,     b3);
+       store_size(b1, avg_objsize);store_size(b2, min_objsize);
+       store_size(b3, max_objsize);
+       printf("User      %10s  %10s  %10s\n",
+                       b1,     b2,     b3);
+
+       store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
+       store_size(b3, max_objwaste);
+       printf("Loss      %10s  %10s  %10s\n",
+                       b1,     b2,     b3);
+}
+
+static void sort_slabs(void)
+{
+       struct slabinfo *s1,*s2;
+
+       for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
+               for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
+                       int result;
+
+                       if (sort_size)
+                               result = slab_size(s1) < slab_size(s2);
+                       else if (sort_active)
+                               result = slab_activity(s1) < slab_activity(s2);
+                       else
+                               result = strcasecmp(s1->name, s2->name);
+
+                       if (show_inverted)
+                               result = -result;
+
+                       if (result > 0) {
+                               struct slabinfo t;
+
+                               memcpy(&t, s1, sizeof(struct slabinfo));
+                               memcpy(s1, s2, sizeof(struct slabinfo));
+                               memcpy(s2, &t, sizeof(struct slabinfo));
+                       }
+               }
+       }
+}
+
+static void sort_aliases(void)
+{
+       struct aliasinfo *a1,*a2;
+
+       for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
+               for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
+                       char *n1, *n2;
+
+                       n1 = a1->name;
+                       n2 = a2->name;
+                       if (show_alias && !show_inverted) {
+                               n1 = a1->ref;
+                               n2 = a2->ref;
+                       }
+                       if (strcasecmp(n1, n2) > 0) {
+                               struct aliasinfo t;
+
+                               memcpy(&t, a1, sizeof(struct aliasinfo));
+                               memcpy(a1, a2, sizeof(struct aliasinfo));
+                               memcpy(a2, &t, sizeof(struct aliasinfo));
+                       }
+               }
+       }
+}
+
+static void link_slabs(void)
+{
+       struct aliasinfo *a;
+       struct slabinfo *s;
+
+       for (a = aliasinfo; a < aliasinfo + aliases; a++) {
+
+               for (s = slabinfo; s < slabinfo + slabs; s++)
+                       if (strcmp(a->ref, s->name) == 0) {
+                               a->slab = s;
+                               s->refs++;
+                               break;
+                       }
+               if (s == slabinfo + slabs)
+                       fatal("Unresolved alias %s\n", a->ref);
+       }
+}
+
+static void alias(void)
+{
+       struct aliasinfo *a;
+       char *active = NULL;
+
+       sort_aliases();
+       link_slabs();
+
+       for(a = aliasinfo; a < aliasinfo + aliases; a++) {
+
+               if (!show_single_ref && a->slab->refs == 1)
+                       continue;
+
+               if (!show_inverted) {
+                       if (active) {
+                               if (strcmp(a->slab->name, active) == 0) {
+                                       printf(" %s", a->name);
+                                       continue;
+                               }
+                       }
+                       printf("\n%-12s <- %s", a->slab->name, a->name);
+                       active = a->slab->name;
+               }
+               else
+                       printf("%-20s -> %s\n", a->name, a->slab->name);
+       }
+       if (active)
+               printf("\n");
+}
+
+
+static void rename_slabs(void)
+{
+       struct slabinfo *s;
+       struct aliasinfo *a;
+
+       for (s = slabinfo; s < slabinfo + slabs; s++) {
+               if (*s->name != ':')
+                       continue;
+
+               if (s->refs > 1 && !show_first_alias)
+                       continue;
+
+               a = find_one_alias(s);
+
+               if (a)
+                       s->name = a->name;
+               else {
+                       s->name = "*";
+                       actual_slabs--;
+               }
+       }
+}
+
+static int slab_mismatch(char *slab)
+{
+       return regexec(&pattern, slab, 0, NULL, 0);
+}
+
+static void read_slab_dir(void)
+{
+       DIR *dir;
+       struct dirent *de;
+       struct slabinfo *slab = slabinfo;
+       struct aliasinfo *alias = aliasinfo;
+       char *p;
+       char *t;
+       int count;
+
+       if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
+               fatal("SYSFS support for SLUB not active\n");
+
+       dir = opendir(".");
+       while ((de = readdir(dir))) {
+               if (de->d_name[0] == '.' ||
+                       (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
+                               continue;
+               switch (de->d_type) {
+                  case DT_LNK:
+                       alias->name = strdup(de->d_name);
+                       count = readlink(de->d_name, buffer, sizeof(buffer)-1);
+
+                       if (count < 0)
+                               fatal("Cannot read symlink %s\n", de->d_name);
+
+                       buffer[count] = 0;
+                       p = buffer + count;
+                       while (p > buffer && p[-1] != '/')
+                               p--;
+                       alias->ref = strdup(p);
+                       alias++;
+                       break;
+                  case DT_DIR:
+                       if (chdir(de->d_name))
+                               fatal("Unable to access slab %s\n", slab->name);
+                       slab->name = strdup(de->d_name);
+                       slab->alias = 0;
+                       slab->refs = 0;
+                       slab->aliases = get_obj("aliases");
+                       slab->align = get_obj("align");
+                       slab->cache_dma = get_obj("cache_dma");
+                       slab->cpu_slabs = get_obj("cpu_slabs");
+                       slab->destroy_by_rcu = get_obj("destroy_by_rcu");
+                       slab->hwcache_align = get_obj("hwcache_align");
+                       slab->object_size = get_obj("object_size");
+                       slab->objects = get_obj("objects");
+                       slab->objects_partial = get_obj("objects_partial");
+                       slab->objects_total = get_obj("objects_total");
+                       slab->objs_per_slab = get_obj("objs_per_slab");
+                       slab->order = get_obj("order");
+                       slab->partial = get_obj("partial");
+                       slab->partial = get_obj_and_str("partial", &t);
+                       decode_numa_list(slab->numa_partial, t);
+                       free(t);
+                       slab->poison = get_obj("poison");
+                       slab->reclaim_account = get_obj("reclaim_account");
+                       slab->red_zone = get_obj("red_zone");
+                       slab->sanity_checks = get_obj("sanity_checks");
+                       slab->slab_size = get_obj("slab_size");
+                       slab->slabs = get_obj_and_str("slabs", &t);
+                       decode_numa_list(slab->numa, t);
+                       free(t);
+                       slab->store_user = get_obj("store_user");
+                       slab->trace = get_obj("trace");
+                       slab->alloc_fastpath = get_obj("alloc_fastpath");
+                       slab->alloc_slowpath = get_obj("alloc_slowpath");
+                       slab->free_fastpath = get_obj("free_fastpath");
+                       slab->free_slowpath = get_obj("free_slowpath");
+                       slab->free_frozen= get_obj("free_frozen");
+                       slab->free_add_partial = get_obj("free_add_partial");
+                       slab->free_remove_partial = get_obj("free_remove_partial");
+                       slab->alloc_from_partial = get_obj("alloc_from_partial");
+                       slab->alloc_slab = get_obj("alloc_slab");
+                       slab->alloc_refill = get_obj("alloc_refill");
+                       slab->free_slab = get_obj("free_slab");
+                       slab->cpuslab_flush = get_obj("cpuslab_flush");
+                       slab->deactivate_full = get_obj("deactivate_full");
+                       slab->deactivate_empty = get_obj("deactivate_empty");
+                       slab->deactivate_to_head = get_obj("deactivate_to_head");
+                       slab->deactivate_to_tail = get_obj("deactivate_to_tail");
+                       slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
+                       slab->order_fallback = get_obj("order_fallback");
+                       slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
+                       slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
+                       slab->cpu_partial_alloc = get_obj("cpu_partial_alloc");
+                       slab->cpu_partial_free = get_obj("cpu_partial_free");
+                       slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
+                       slab->deactivate_bypass = get_obj("deactivate_bypass");
+                       chdir("..");
+                       if (slab->name[0] == ':')
+                               alias_targets++;
+                       slab++;
+                       break;
+                  default :
+                       fatal("Unknown file type %lx\n", de->d_type);
+               }
+       }
+       closedir(dir);
+       slabs = slab - slabinfo;
+       actual_slabs = slabs;
+       aliases = alias - aliasinfo;
+       if (slabs > MAX_SLABS)
+               fatal("Too many slabs\n");
+       if (aliases > MAX_ALIASES)
+               fatal("Too many aliases\n");
+}
+
+static void output_slabs(void)
+{
+       struct slabinfo *slab;
+
+       for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
+
+               if (slab->alias)
+                       continue;
+
+
+               if (show_numa)
+                       slab_numa(slab, 0);
+               else if (show_track)
+                       show_tracking(slab);
+               else if (validate)
+                       slab_validate(slab);
+               else if (shrink)
+                       slab_shrink(slab);
+               else if (set_debug)
+                       slab_debug(slab);
+               else if (show_ops)
+                       ops(slab);
+               else if (show_slab)
+                       slabcache(slab);
+               else if (show_report)
+                       report(slab);
+       }
+}
+
+struct option opts[] = {
+       { "aliases", 0, NULL, 'a' },
+       { "activity", 0, NULL, 'A' },
+       { "debug", 2, NULL, 'd' },
+       { "display-activity", 0, NULL, 'D' },
+       { "empty", 0, NULL, 'e' },
+       { "first-alias", 0, NULL, 'f' },
+       { "help", 0, NULL, 'h' },
+       { "inverted", 0, NULL, 'i'},
+       { "numa", 0, NULL, 'n' },
+       { "ops", 0, NULL, 'o' },
+       { "report", 0, NULL, 'r' },
+       { "shrink", 0, NULL, 's' },
+       { "slabs", 0, NULL, 'l' },
+       { "track", 0, NULL, 't'},
+       { "validate", 0, NULL, 'v' },
+       { "zero", 0, NULL, 'z' },
+       { "1ref", 0, NULL, '1'},
+       { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+       int c;
+       int err;
+       char *pattern_source;
+
+       page_size = getpagesize();
+
+       while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTS",
+                                               opts, NULL)) != -1)
+               switch (c) {
+               case '1':
+                       show_single_ref = 1;
+                       break;
+               case 'a':
+                       show_alias = 1;
+                       break;
+               case 'A':
+                       sort_active = 1;
+                       break;
+               case 'd':
+                       set_debug = 1;
+                       if (!debug_opt_scan(optarg))
+                               fatal("Invalid debug option '%s'\n", optarg);
+                       break;
+               case 'D':
+                       show_activity = 1;
+                       break;
+               case 'e':
+                       show_empty = 1;
+                       break;
+               case 'f':
+                       show_first_alias = 1;
+                       break;
+               case 'h':
+                       usage();
+                       return 0;
+               case 'i':
+                       show_inverted = 1;
+                       break;
+               case 'n':
+                       show_numa = 1;
+                       break;
+               case 'o':
+                       show_ops = 1;
+                       break;
+               case 'r':
+                       show_report = 1;
+                       break;
+               case 's':
+                       shrink = 1;
+                       break;
+               case 'l':
+                       show_slab = 1;
+                       break;
+               case 't':
+                       show_track = 1;
+                       break;
+               case 'v':
+                       validate = 1;
+                       break;
+               case 'z':
+                       skip_zero = 0;
+                       break;
+               case 'T':
+                       show_totals = 1;
+                       break;
+               case 'S':
+                       sort_size = 1;
+                       break;
+
+               default:
+                       fatal("%s: Invalid option '%c'\n", argv[0], optopt);
+
+       }
+
+       if (!show_slab && !show_alias && !show_track && !show_report
+               && !validate && !shrink && !set_debug && !show_ops)
+                       show_slab = 1;
+
+       if (argc > optind)
+               pattern_source = argv[optind];
+       else
+               pattern_source = ".*";
+
+       err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
+       if (err)
+               fatal("%s: Invalid pattern '%s' code %d\n",
+                       argv[0], pattern_source, err);
+       read_slab_dir();
+       if (show_alias)
+               alias();
+       else
+       if (show_totals)
+               totals();
+       else {
+               link_slabs();
+               rename_slabs();
+               sort_slabs();
+               output_slabs();
+       }
+       return 0;
+}
index 758e3b36d4cfd525846a1968987d80bea8e4bcce..01f572c10c71c1ba2fb5775320600b61829e73c6 100644 (file)
@@ -49,31 +49,73 @@ static int find_index_from_host_irq(struct kvm_assigned_dev_kernel
                        index = i;
                        break;
                }
-       if (index < 0) {
+       if (index < 0)
                printk(KERN_WARNING "Fail to find correlated MSI-X entry!\n");
-               return 0;
-       }
 
        return index;
 }
 
-static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id)
+static irqreturn_t kvm_assigned_dev_intx(int irq, void *dev_id)
 {
        struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+       int ret;
+
+       spin_lock(&assigned_dev->intx_lock);
+       if (pci_check_and_mask_intx(assigned_dev->dev)) {
+               assigned_dev->host_irq_disabled = true;
+               ret = IRQ_WAKE_THREAD;
+       } else
+               ret = IRQ_NONE;
+       spin_unlock(&assigned_dev->intx_lock);
+
+       return ret;
+}
 
-       if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_INTX) {
-               spin_lock(&assigned_dev->intx_lock);
+static void
+kvm_assigned_dev_raise_guest_irq(struct kvm_assigned_dev_kernel *assigned_dev,
+                                int vector)
+{
+       if (unlikely(assigned_dev->irq_requested_type &
+                    KVM_DEV_IRQ_GUEST_INTX)) {
+               spin_lock(&assigned_dev->intx_mask_lock);
+               if (!(assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX))
+                       kvm_set_irq(assigned_dev->kvm,
+                                   assigned_dev->irq_source_id, vector, 1);
+               spin_unlock(&assigned_dev->intx_mask_lock);
+       } else
+               kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
+                           vector, 1);
+}
+
+static irqreturn_t kvm_assigned_dev_thread_intx(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+
+       if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
+               spin_lock_irq(&assigned_dev->intx_lock);
                disable_irq_nosync(irq);
                assigned_dev->host_irq_disabled = true;
-               spin_unlock(&assigned_dev->intx_lock);
+               spin_unlock_irq(&assigned_dev->intx_lock);
        }
 
-       kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
-                   assigned_dev->guest_irq, 1);
+       kvm_assigned_dev_raise_guest_irq(assigned_dev,
+                                        assigned_dev->guest_irq);
 
        return IRQ_HANDLED;
 }
 
+#ifdef __KVM_HAVE_MSI
+static irqreturn_t kvm_assigned_dev_thread_msi(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+
+       kvm_assigned_dev_raise_guest_irq(assigned_dev,
+                                        assigned_dev->guest_irq);
+
+       return IRQ_HANDLED;
+}
+#endif
+
 #ifdef __KVM_HAVE_MSIX
 static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
 {
@@ -83,8 +125,7 @@ static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
 
        if (index >= 0) {
                vector = assigned_dev->guest_msix_entries[index].vector;
-               kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
-                           vector, 1);
+               kvm_assigned_dev_raise_guest_irq(assigned_dev, vector);
        }
 
        return IRQ_HANDLED;
@@ -100,15 +141,31 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
 
        kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0);
 
-       /* The guest irq may be shared so this ack may be
-        * from another device.
-        */
-       spin_lock(&dev->intx_lock);
-       if (dev->host_irq_disabled) {
-               enable_irq(dev->host_irq);
-               dev->host_irq_disabled = false;
+       spin_lock(&dev->intx_mask_lock);
+
+       if (!(dev->flags & KVM_DEV_ASSIGN_MASK_INTX)) {
+               bool reassert = false;
+
+               spin_lock_irq(&dev->intx_lock);
+               /*
+                * The guest IRQ may be shared so this ack can come from an
+                * IRQ for another guest device.
+                */
+               if (dev->host_irq_disabled) {
+                       if (!(dev->flags & KVM_DEV_ASSIGN_PCI_2_3))
+                               enable_irq(dev->host_irq);
+                       else if (!pci_check_and_unmask_intx(dev->dev))
+                               reassert = true;
+                       dev->host_irq_disabled = reassert;
+               }
+               spin_unlock_irq(&dev->intx_lock);
+
+               if (reassert)
+                       kvm_set_irq(dev->kvm, dev->irq_source_id,
+                                   dev->guest_irq, 1);
        }
-       spin_unlock(&dev->intx_lock);
+
+       spin_unlock(&dev->intx_mask_lock);
 }
 
 static void deassign_guest_irq(struct kvm *kvm,
@@ -156,7 +213,15 @@ static void deassign_host_irq(struct kvm *kvm,
                pci_disable_msix(assigned_dev->dev);
        } else {
                /* Deal with MSI and INTx */
-               disable_irq(assigned_dev->host_irq);
+               if ((assigned_dev->irq_requested_type &
+                    KVM_DEV_IRQ_HOST_INTX) &&
+                   (assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
+                       spin_lock_irq(&assigned_dev->intx_lock);
+                       pci_intx(assigned_dev->dev, false);
+                       spin_unlock_irq(&assigned_dev->intx_lock);
+                       synchronize_irq(assigned_dev->host_irq);
+               } else
+                       disable_irq(assigned_dev->host_irq);
 
                free_irq(assigned_dev->host_irq, assigned_dev);
 
@@ -237,15 +302,34 @@ void kvm_free_all_assigned_devices(struct kvm *kvm)
 static int assigned_device_enable_host_intx(struct kvm *kvm,
                                            struct kvm_assigned_dev_kernel *dev)
 {
+       irq_handler_t irq_handler;
+       unsigned long flags;
+
        dev->host_irq = dev->dev->irq;
-       /* Even though this is PCI, we don't want to use shared
-        * interrupts. Sharing host devices with guest-assigned devices
-        * on the same interrupt line is not a happy situation: there
-        * are going to be long delays in accepting, acking, etc.
+
+       /*
+        * We can only share the IRQ line with other host devices if we are
+        * able to disable the IRQ source at device-level - independently of
+        * the guest driver. Otherwise host devices may suffer from unbounded
+        * IRQ latencies when the guest keeps the line asserted.
         */
-       if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
-                                IRQF_ONESHOT, dev->irq_name, dev))
+       if (dev->flags & KVM_DEV_ASSIGN_PCI_2_3) {
+               irq_handler = kvm_assigned_dev_intx;
+               flags = IRQF_SHARED;
+       } else {
+               irq_handler = NULL;
+               flags = IRQF_ONESHOT;
+       }
+       if (request_threaded_irq(dev->host_irq, irq_handler,
+                                kvm_assigned_dev_thread_intx, flags,
+                                dev->irq_name, dev))
                return -EIO;
+
+       if (dev->flags & KVM_DEV_ASSIGN_PCI_2_3) {
+               spin_lock_irq(&dev->intx_lock);
+               pci_intx(dev->dev, true);
+               spin_unlock_irq(&dev->intx_lock);
+       }
        return 0;
 }
 
@@ -262,8 +346,9 @@ static int assigned_device_enable_host_msi(struct kvm *kvm,
        }
 
        dev->host_irq = dev->dev->irq;
-       if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
-                                0, dev->irq_name, dev)) {
+       if (request_threaded_irq(dev->host_irq, NULL,
+                                kvm_assigned_dev_thread_msi, 0,
+                                dev->irq_name, dev)) {
                pci_disable_msi(dev->dev);
                return -EIO;
        }
@@ -321,7 +406,6 @@ static int assigned_device_enable_guest_msi(struct kvm *kvm,
 {
        dev->guest_irq = irq->guest_irq;
        dev->ack_notifier.gsi = -1;
-       dev->host_irq_disabled = false;
        return 0;
 }
 #endif
@@ -333,7 +417,6 @@ static int assigned_device_enable_guest_msix(struct kvm *kvm,
 {
        dev->guest_irq = irq->guest_irq;
        dev->ack_notifier.gsi = -1;
-       dev->host_irq_disabled = false;
        return 0;
 }
 #endif
@@ -367,6 +450,7 @@ static int assign_host_irq(struct kvm *kvm,
        default:
                r = -EINVAL;
        }
+       dev->host_irq_disabled = false;
 
        if (!r)
                dev->irq_requested_type |= host_irq_type;
@@ -468,6 +552,7 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
 {
        int r = -ENODEV;
        struct kvm_assigned_dev_kernel *match;
+       unsigned long irq_type;
 
        mutex_lock(&kvm->lock);
 
@@ -476,7 +561,9 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
        if (!match)
                goto out;
 
-       r = kvm_deassign_irq(kvm, match, assigned_irq->flags);
+       irq_type = assigned_irq->flags & (KVM_DEV_IRQ_HOST_MASK |
+                                         KVM_DEV_IRQ_GUEST_MASK);
+       r = kvm_deassign_irq(kvm, match, irq_type);
 out:
        mutex_unlock(&kvm->lock);
        return r;
@@ -609,6 +696,10 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        if (!match->pci_saved_state)
                printk(KERN_DEBUG "%s: Couldn't store %s saved state\n",
                       __func__, dev_name(&dev->dev));
+
+       if (!pci_intx_mask_supported(dev))
+               assigned_dev->flags &= ~KVM_DEV_ASSIGN_PCI_2_3;
+
        match->assigned_dev_id = assigned_dev->assigned_dev_id;
        match->host_segnr = assigned_dev->segnr;
        match->host_busnr = assigned_dev->busnr;
@@ -616,6 +707,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        match->flags = assigned_dev->flags;
        match->dev = dev;
        spin_lock_init(&match->intx_lock);
+       spin_lock_init(&match->intx_mask_lock);
        match->irq_source_id = -1;
        match->kvm = kvm;
        match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
@@ -761,6 +853,55 @@ msix_entry_out:
 }
 #endif
 
+static int kvm_vm_ioctl_set_pci_irq_mask(struct kvm *kvm,
+               struct kvm_assigned_pci_dev *assigned_dev)
+{
+       int r = 0;
+       struct kvm_assigned_dev_kernel *match;
+
+       mutex_lock(&kvm->lock);
+
+       match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+                                     assigned_dev->assigned_dev_id);
+       if (!match) {
+               r = -ENODEV;
+               goto out;
+       }
+
+       spin_lock(&match->intx_mask_lock);
+
+       match->flags &= ~KVM_DEV_ASSIGN_MASK_INTX;
+       match->flags |= assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX;
+
+       if (match->irq_requested_type & KVM_DEV_IRQ_GUEST_INTX) {
+               if (assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX) {
+                       kvm_set_irq(match->kvm, match->irq_source_id,
+                                   match->guest_irq, 0);
+                       /*
+                        * Masking at hardware-level is performed on demand,
+                        * i.e. when an IRQ actually arrives at the host.
+                        */
+               } else if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
+                       /*
+                        * Unmask the IRQ line if required. Unmasking at
+                        * device level will be performed by user space.
+                        */
+                       spin_lock_irq(&match->intx_lock);
+                       if (match->host_irq_disabled) {
+                               enable_irq(match->host_irq);
+                               match->host_irq_disabled = false;
+                       }
+                       spin_unlock_irq(&match->intx_lock);
+               }
+       }
+
+       spin_unlock(&match->intx_mask_lock);
+
+out:
+       mutex_unlock(&kvm->lock);
+       return r;
+}
+
 long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
                                  unsigned long arg)
 {
@@ -868,6 +1009,15 @@ long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
                break;
        }
 #endif
+       case KVM_ASSIGN_SET_INTX_MASK: {
+               struct kvm_assigned_pci_dev assigned_dev;
+
+               r = -EFAULT;
+               if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev))
+                       goto out;
+               r = kvm_vm_ioctl_set_pci_irq_mask(kvm, &assigned_dev);
+               break;
+       }
        default:
                r = -ENOTTY;
                break;
@@ -875,4 +1025,3 @@ long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
 out:
        return r;
 }
-
index a91f980077d843ca319dfe5d7b3b95e252e02bc3..42b73930a6de6b2210708aca55903f87a9bab459 100644 (file)
@@ -203,7 +203,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
 
 void kvm_flush_remote_tlbs(struct kvm *kvm)
 {
-       int dirty_count = kvm->tlbs_dirty;
+       long dirty_count = kvm->tlbs_dirty;
 
        smp_mb();
        if (make_all_cpus_request(kvm, KVM_REQ_TLB_FLUSH))
@@ -289,15 +289,15 @@ static void kvm_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
         */
        idx = srcu_read_lock(&kvm->srcu);
        spin_lock(&kvm->mmu_lock);
+
        kvm->mmu_notifier_seq++;
        need_tlb_flush = kvm_unmap_hva(kvm, address) | kvm->tlbs_dirty;
-       spin_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
-
        /* we've to flush the tlb before the pages can be freed */
        if (need_tlb_flush)
                kvm_flush_remote_tlbs(kvm);
 
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
 }
 
 static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
@@ -335,12 +335,12 @@ static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
        for (; start < end; start += PAGE_SIZE)
                need_tlb_flush |= kvm_unmap_hva(kvm, start);
        need_tlb_flush |= kvm->tlbs_dirty;
-       spin_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
-
        /* we've to flush the tlb before the pages can be freed */
        if (need_tlb_flush)
                kvm_flush_remote_tlbs(kvm);
+
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
 }
 
 static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
@@ -357,11 +357,11 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
         * been freed.
         */
        kvm->mmu_notifier_seq++;
+       smp_wmb();
        /*
         * The above sequence increase must be visible before the
-        * below count decrease but both values are read by the kvm
-        * page fault under mmu_lock spinlock so we don't need to add
-        * a smb_wmb() here in between the two.
+        * below count decrease, which is ensured by the smp_wmb above
+        * in conjunction with the smp_rmb in mmu_notifier_retry().
         */
        kvm->mmu_notifier_count--;
        spin_unlock(&kvm->mmu_lock);
@@ -378,13 +378,14 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
 
        idx = srcu_read_lock(&kvm->srcu);
        spin_lock(&kvm->mmu_lock);
-       young = kvm_age_hva(kvm, address);
-       spin_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
 
+       young = kvm_age_hva(kvm, address);
        if (young)
                kvm_flush_remote_tlbs(kvm);
 
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
+
        return young;
 }
 
@@ -449,7 +450,7 @@ static void kvm_init_memslots_id(struct kvm *kvm)
                slots->id_to_index[i] = slots->memslots[i].id = i;
 }
 
-static struct kvm *kvm_create_vm(void)
+static struct kvm *kvm_create_vm(unsigned long type)
 {
        int r, i;
        struct kvm *kvm = kvm_arch_alloc_vm();
@@ -457,7 +458,7 @@ static struct kvm *kvm_create_vm(void)
        if (!kvm)
                return ERR_PTR(-ENOMEM);
 
-       r = kvm_arch_init_vm(kvm);
+       r = kvm_arch_init_vm(kvm, type);
        if (r)
                goto out_err_nodisable;
 
@@ -535,21 +536,13 @@ static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot)
 static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
                                  struct kvm_memory_slot *dont)
 {
-       int i;
-
        if (!dont || free->rmap != dont->rmap)
                vfree(free->rmap);
 
        if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
                kvm_destroy_dirty_bitmap(free);
 
-
-       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
-               if (!dont || free->lpage_info[i] != dont->lpage_info[i]) {
-                       vfree(free->lpage_info[i]);
-                       free->lpage_info[i] = NULL;
-               }
-       }
+       kvm_arch_free_memslot(free, dont);
 
        free->npages = 0;
        free->rmap = NULL;
@@ -616,7 +609,6 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
-#ifndef CONFIG_S390
 /*
  * Allocation size is twice as large as the actual dirty bitmap size.
  * This makes it possible to do double buffering: see x86's
@@ -624,6 +616,7 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
  */
 static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
 {
+#ifndef CONFIG_S390
        unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);
 
        if (dirty_bytes > PAGE_SIZE)
@@ -636,21 +629,8 @@ static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
 
        memslot->dirty_bitmap_head = memslot->dirty_bitmap;
        memslot->nr_dirty_pages = 0;
-       return 0;
-}
 #endif /* !CONFIG_S390 */
-
-static struct kvm_memory_slot *
-search_memslots(struct kvm_memslots *slots, gfn_t gfn)
-{
-       struct kvm_memory_slot *memslot;
-
-       kvm_for_each_memslot(memslot, slots)
-               if (gfn >= memslot->base_gfn &&
-                     gfn < memslot->base_gfn + memslot->npages)
-                       return memslot;
-
-       return NULL;
+       return 0;
 }
 
 static int cmp_memslot(const void *slot1, const void *slot2)
@@ -778,69 +758,24 @@ int __kvm_set_memory_region(struct kvm *kvm,
        r = -ENOMEM;
 
        /* Allocate if a slot is being created */
+       if (npages && !old.npages) {
+               new.user_alloc = user_alloc;
+               new.userspace_addr = mem->userspace_addr;
 #ifndef CONFIG_S390
-       if (npages && !new.rmap) {
                new.rmap = vzalloc(npages * sizeof(*new.rmap));
-
                if (!new.rmap)
                        goto out_free;
-
-               new.user_alloc = user_alloc;
-               new.userspace_addr = mem->userspace_addr;
-       }
-       if (!npages)
-               goto skip_lpage;
-
-       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
-               unsigned long ugfn;
-               unsigned long j;
-               int lpages;
-               int level = i + 2;
-
-               /* Avoid unused variable warning if no large pages */
-               (void)level;
-
-               if (new.lpage_info[i])
-                       continue;
-
-               lpages = 1 + ((base_gfn + npages - 1)
-                            >> KVM_HPAGE_GFN_SHIFT(level));
-               lpages -= base_gfn >> KVM_HPAGE_GFN_SHIFT(level);
-
-               new.lpage_info[i] = vzalloc(lpages * sizeof(*new.lpage_info[i]));
-
-               if (!new.lpage_info[i])
+#endif /* not defined CONFIG_S390 */
+               if (kvm_arch_create_memslot(&new, npages))
                        goto out_free;
-
-               if (base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
-                       new.lpage_info[i][0].write_count = 1;
-               if ((base_gfn+npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
-                       new.lpage_info[i][lpages - 1].write_count = 1;
-               ugfn = new.userspace_addr >> PAGE_SHIFT;
-               /*
-                * If the gfn and userspace address are not aligned wrt each
-                * other, or if explicitly asked to, disable large page
-                * support for this slot
-                */
-               if ((base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) ||
-                   !largepages_enabled)
-                       for (j = 0; j < lpages; ++j)
-                               new.lpage_info[i][j].write_count = 1;
        }
 
-skip_lpage:
-
        /* Allocate page dirty bitmap if needed */
        if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
                if (kvm_create_dirty_bitmap(&new) < 0)
                        goto out_free;
                /* destroy any largepage mappings for dirty tracking */
        }
-#else  /* not defined CONFIG_S390 */
-       new.user_alloc = user_alloc;
-       if (user_alloc)
-               new.userspace_addr = mem->userspace_addr;
-#endif /* not defined CONFIG_S390 */
 
        if (!npages) {
                struct kvm_memory_slot *slot;
@@ -890,8 +825,7 @@ skip_lpage:
        if (!npages) {
                new.rmap = NULL;
                new.dirty_bitmap = NULL;
-               for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i)
-                       new.lpage_info[i] = NULL;
+               memset(&new.arch, 0, sizeof(new.arch));
        }
 
        update_memslots(slots, &new);
@@ -978,6 +912,11 @@ out:
        return r;
 }
 
+bool kvm_largepages_enabled(void)
+{
+       return largepages_enabled;
+}
+
 void kvm_disable_largepages(void)
 {
        largepages_enabled = false;
@@ -1031,12 +970,6 @@ int kvm_is_error_hva(unsigned long addr)
 }
 EXPORT_SYMBOL_GPL(kvm_is_error_hva);
 
-static struct kvm_memory_slot *__gfn_to_memslot(struct kvm_memslots *slots,
-                                               gfn_t gfn)
-{
-       return search_memslots(slots, gfn);
-}
-
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
 {
        return __gfn_to_memslot(kvm_memslots(kvm), gfn);
@@ -1459,7 +1392,7 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 
        ghc->gpa = gpa;
        ghc->generation = slots->generation;
-       ghc->memslot = __gfn_to_memslot(slots, gfn);
+       ghc->memslot = gfn_to_memslot(kvm, gfn);
        ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL);
        if (!kvm_is_error_hva(ghc->hva))
                ghc->hva += offset;
@@ -1657,7 +1590,7 @@ static int kvm_vcpu_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                page = virt_to_page(vcpu->kvm->coalesced_mmio_ring);
 #endif
        else
-               return VM_FAULT_SIGBUS;
+               return kvm_arch_vcpu_fault(vcpu, vmf);
        get_page(page);
        vmf->page = page;
        return 0;
@@ -1718,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
                goto vcpu_destroy;
 
        mutex_lock(&kvm->lock);
+       if (!kvm_vcpu_compatible(vcpu)) {
+               r = -EINVAL;
+               goto unlock_vcpu_destroy;
+       }
        if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
                r = -EINVAL;
                goto unlock_vcpu_destroy;
@@ -2198,12 +2135,12 @@ static struct file_operations kvm_vm_fops = {
        .llseek         = noop_llseek,
 };
 
-static int kvm_dev_ioctl_create_vm(void)
+static int kvm_dev_ioctl_create_vm(unsigned long type)
 {
        int r;
        struct kvm *kvm;
 
-       kvm = kvm_create_vm();
+       kvm = kvm_create_vm(type);
        if (IS_ERR(kvm))
                return PTR_ERR(kvm);
 #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
@@ -2254,10 +2191,7 @@ static long kvm_dev_ioctl(struct file *filp,
                r = KVM_API_VERSION;
                break;
        case KVM_CREATE_VM:
-               r = -EINVAL;
-               if (arg)
-                       goto out;
-               r = kvm_dev_ioctl_create_vm();
+               r = kvm_dev_ioctl_create_vm(arg);
                break;
        case KVM_CHECK_EXTENSION:
                r = kvm_dev_ioctl_check_extension_generic(arg);